2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSWorker.cpp
39 #include "AFSCommon.h"
42 // Function: AFSInitializeWorkerPool
46 // This function initializes the worker thread pool
50 // A status is returned for the function
54 AFSInitializeWorkerPool()
57 NTSTATUS ntStatus = STATUS_SUCCESS;
58 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
59 AFSDeviceExt *pDevExt = NULL;
64 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
67 // Initialize the worker threads.
70 pDevExt->Specific.Library.WorkerCount = 0;
72 KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
77 // Initialize the queue resource
80 ExInitializeResourceLite( &pDevExt->Specific.Library.QueueLock);
82 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
85 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
86 sizeof( AFSWorkQueueContext),
89 if( pCurrentWorker == NULL)
92 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
93 AFS_TRACE_LEVEL_ERROR,
94 "AFSInitializeWorkerPool Failed to allocate worker context\n");
96 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
101 RtlZeroMemory( pCurrentWorker,
102 sizeof( AFSWorkQueueContext));
104 ntStatus = AFSInitWorkerThread( pCurrentWorker,
105 (PKSTART_ROUTINE)AFSWorkerThread);
107 if( !NT_SUCCESS( ntStatus))
110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
111 AFS_TRACE_LEVEL_ERROR,
112 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
114 ExFreePool( pCurrentWorker);
119 if( pDevExt->Specific.Library.PoolHead == NULL)
122 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
127 pLastWorker->fLink = pCurrentWorker;
130 pLastWorker = pCurrentWorker;
132 pDevExt->Specific.Library.WorkerCount++;
136 // If there was a failure but there is at least one worker, then go with it.
139 if( !NT_SUCCESS( ntStatus) &&
140 pDevExt->Specific.Library.WorkerCount == 0)
143 try_return( ntStatus);
146 ntStatus = STATUS_SUCCESS;
149 // Now our IO Worker queue
152 pDevExt->Specific.Library.IOWorkerCount = 0;
154 KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
159 // Initialize the queue resource
162 ExInitializeResourceLite( &pDevExt->Specific.Library.IOQueueLock);
164 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
167 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
168 sizeof( AFSWorkQueueContext),
171 if( pCurrentWorker == NULL)
174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
178 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
183 RtlZeroMemory( pCurrentWorker,
184 sizeof( AFSWorkQueueContext));
186 ntStatus = AFSInitWorkerThread( pCurrentWorker,
187 (PKSTART_ROUTINE)AFSIOWorkerThread);
189 if( !NT_SUCCESS( ntStatus))
192 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
193 AFS_TRACE_LEVEL_ERROR,
194 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
196 ExFreePool( pCurrentWorker);
201 if( pDevExt->Specific.Library.IOPoolHead == NULL)
204 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
209 pLastWorker->fLink = pCurrentWorker;
212 pLastWorker = pCurrentWorker;
214 pDevExt->Specific.Library.IOWorkerCount++;
218 // If there was a failure but there is at least one worker, then go with it.
221 if( !NT_SUCCESS( ntStatus) &&
222 pDevExt->Specific.Library.IOWorkerCount == 0)
225 try_return( ntStatus);
230 if( !NT_SUCCESS( ntStatus))
234 // Failed to initialize the pool so tear it down
237 AFSRemoveWorkerPool();
245 // Function: AFSRemoveWorkerPool
249 // This function tears down the worker thread pool
253 // A status is returned for the function
257 AFSRemoveWorkerPool()
260 NTSTATUS ntStatus = STATUS_SUCCESS;
262 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
263 AFSDeviceExt *pDevExt = NULL;
265 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
268 // Loop through the workers shutting them down
271 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
273 while( index < pDevExt->Specific.Library.WorkerCount)
276 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
278 pNextWorker = pCurrentWorker->fLink;
280 ExFreePool( pCurrentWorker);
282 pCurrentWorker = pNextWorker;
284 if( pCurrentWorker == NULL)
293 pDevExt->Specific.Library.PoolHead = NULL;
295 ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
298 // Loop through the IO workers shutting them down
301 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
305 while( index < pDevExt->Specific.Library.IOWorkerCount)
308 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
310 pNextWorker = pCurrentWorker->fLink;
312 ExFreePool( pCurrentWorker);
314 pCurrentWorker = pNextWorker;
316 if( pCurrentWorker == NULL)
325 pDevExt->Specific.Library.IOPoolHead = NULL;
327 ExDeleteResourceLite( &pDevExt->Specific.Library.IOQueueLock);
333 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
336 NTSTATUS ntStatus = STATUS_SUCCESS;
337 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
339 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
340 PKSTART_ROUTINE pStartRoutine = NULL;
345 if( VolumeCB == AFSGlobalRoot)
348 pStartRoutine = AFSPrimaryVolumeWorkerThread;
353 pStartRoutine = AFSVolumeWorkerThread;
357 // Initialize the worker thread
360 KeInitializeEvent( &pWorker->WorkerThreadReady,
365 // Set the worker to process requests
368 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
374 ntStatus = PsCreateSystemThread( &hThread,
382 if( NT_SUCCESS( ntStatus))
385 ObReferenceObjectByHandle( hThread,
386 GENERIC_READ | GENERIC_WRITE,
389 (PVOID *)&pWorker->WorkerThreadObject,
392 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
398 if( InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) > 0)
401 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
412 // Function: AFSInitWorkerThread
416 // This function initializes a worker thread in the pool
420 // A status is returned for the function
424 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
425 IN PKSTART_ROUTINE WorkerRoutine)
428 NTSTATUS ntStatus = STATUS_SUCCESS;
432 // INitialize the worker signal thread
435 KeInitializeEvent( &PoolContext->WorkerThreadReady,
440 // Set the worker to process requests
443 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
449 ntStatus = PsCreateSystemThread( &Handle,
455 (void *)PoolContext);
457 if( NT_SUCCESS( ntStatus))
460 ObReferenceObjectByHandle( Handle,
461 GENERIC_READ | GENERIC_WRITE,
464 (PVOID *)&PoolContext->WorkerThreadObject,
467 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
480 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
483 NTSTATUS ntStatus = STATUS_SUCCESS;
484 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
486 if( pWorker->WorkerThreadObject != NULL &&
487 BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED))
491 // Clear the 'keep processing' flag
494 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
496 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
502 ObDereferenceObject( pWorker->WorkerThreadObject);
504 pWorker->WorkerThreadObject = NULL;
511 // Function: AFSShutdownWorkerThread
515 // This function shusdown a worker thread in the pool
519 // A status is returned for the function
523 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
526 NTSTATUS ntStatus = STATUS_SUCCESS;
527 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
529 if( PoolContext->WorkerThreadObject != NULL &&
530 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
534 // Clear the 'keep processing' flag
537 ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
540 // Wake up the thread if it is a sleep
543 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
547 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
553 ObDereferenceObject( PoolContext->WorkerThreadObject);
555 PoolContext->WorkerThreadObject = NULL;
562 // Function: AFSShutdownIOWorkerThread
566 // This function shutsdown an IO worker thread in the pool
570 // A status is returned for the function
574 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
577 NTSTATUS ntStatus = STATUS_SUCCESS;
578 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
580 if( PoolContext->WorkerThreadObject != NULL &&
581 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
585 // Clear the 'keep processing' flag
588 ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
591 // Wake up the thread if it is a sleep
594 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
598 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
604 ObDereferenceObject( PoolContext->WorkerThreadObject);
606 PoolContext->WorkerThreadObject = NULL;
613 // Function: AFSWorkerThread
617 // This is the worker thread entry point.
621 // A status is returned for the function
625 AFSWorkerThread( IN PVOID Context)
628 NTSTATUS ntStatus = STATUS_SUCCESS;
629 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
630 AFSWorkItem *pWorkItem;
631 BOOLEAN freeWorkItem = TRUE;
632 BOOLEAN exitThread = FALSE;
633 AFSDeviceExt *pLibraryDevExt = NULL;
635 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
638 // Indicate that we are initialized and ready
641 KeSetEvent( &pPoolContext->WorkerThreadReady,
647 // Indicate we are initialized
650 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
652 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
655 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
661 if( !NT_SUCCESS( ntStatus))
664 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
665 AFS_TRACE_LEVEL_ERROR,
666 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
671 pWorkItem = AFSRemoveWorkItem();
673 if( pWorkItem != NULL)
679 // Switch on the type of work item to process
682 switch( pWorkItem->RequestType)
685 case AFS_WORK_FLUSH_FCB:
688 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb);
690 if( !NT_SUCCESS( ntStatus))
693 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb);
696 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
698 InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
703 case AFS_WORK_ASYNCH_READ:
706 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
708 (VOID) AFSCommonRead( pWorkItem->Specific.AsynchIo.Device,
709 pWorkItem->Specific.AsynchIo.Irp,
710 pWorkItem->Specific.AsynchIo.CallingProcess);
715 case AFS_WORK_ASYNCH_WRITE:
718 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
720 (VOID) AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
721 pWorkItem->Specific.AsynchIo.Irp,
722 pWorkItem->Specific.AsynchIo.CallingProcess);
726 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
729 AFSEnumerateGlobalRoot( NULL);
734 case AFS_WORK_START_IOS:
744 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
745 AFS_TRACE_LEVEL_ERROR,
746 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
754 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
758 } // worker thread loop
760 PsTerminateSystemThread( 0);
766 AFSIOWorkerThread( IN PVOID Context)
769 NTSTATUS ntStatus = STATUS_SUCCESS;
770 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
771 AFSWorkItem *pWorkItem;
772 BOOLEAN freeWorkItem = TRUE;
773 BOOLEAN exitThread = FALSE;
774 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
776 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
779 // Indicate that we are initialized and ready
782 KeSetEvent( &pPoolContext->WorkerThreadReady,
788 // Indicate we are initialized
791 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
793 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
796 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
802 if( !NT_SUCCESS( ntStatus))
805 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
806 AFS_TRACE_LEVEL_ERROR,
807 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
812 pWorkItem = AFSRemoveIOWorkItem();
814 if( pWorkItem != NULL)
820 // Switch on the type of work item to process
823 switch( pWorkItem->RequestType)
826 case AFS_WORK_START_IOS:
829 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
832 // The final status is in the gather io
835 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
836 pWorkItem->Specific.CacheAccess.FunctionCode,
837 pWorkItem->Specific.CacheAccess.RequestFlags,
838 pWorkItem->Specific.CacheAccess.IoRuns,
839 pWorkItem->Specific.CacheAccess.RunCount,
840 pWorkItem->Specific.CacheAccess.GatherIo);
843 // Regardless of the status we we do the complete - there may
845 // Decrement the count - setting the event if we were told
846 // to. This may trigger completion.
849 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
858 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
859 AFS_TRACE_LEVEL_ERROR,
860 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
868 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
872 } // worker thread loop
874 PsTerminateSystemThread( 0);
880 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
883 NTSTATUS ntStatus = STATUS_SUCCESS;
884 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
885 AFSDeviceExt *pControlDeviceExt = NULL;
886 AFSDeviceExt *pRDRDeviceExt = NULL;
887 BOOLEAN exitThread = FALSE;
888 LARGE_INTEGER DueTime;
891 BOOLEAN bFoundOpenEntry = FALSE;
892 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
893 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
894 BOOLEAN bReleaseVolumeLock = FALSE;
895 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
896 LARGE_INTEGER liCurrentTime;
897 BOOLEAN bVolumeObject = FALSE;
899 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
901 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
903 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
904 AFS_TRACE_LEVEL_VERBOSE,
905 "AFSPrimaryVolumeWorkerThread Initialized\n");
908 // Initialize the timer for the worker thread
911 DueTime.QuadPart = -(5000);
915 KeInitializeTimerEx( &Timer,
916 SynchronizationTimer);
918 KeSetTimerEx( &Timer,
924 // Indicate that we are initialized and ready
927 KeSetEvent( &pPoolContext->WorkerThreadReady,
932 // Indicate we are initialized
935 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
937 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
940 KeWaitForSingleObject( &Timer,
947 // This is the primary volume worker so it will traverse the volume list
948 // looking for cleanup or volumes requiring private workers
951 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
954 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
956 while( pVolumeCB != NULL)
959 if( pVolumeCB == AFSGlobalRoot ||
960 !AFSAcquireExcl( pVolumeCB->VolumeLock,
964 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
969 if( pVolumeCB->ObjectInfoListHead == NULL &&
970 pVolumeCB != AFSGlobalRoot)
973 AFSReleaseResource( pVolumeCB->VolumeLock);
975 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
977 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
980 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
983 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
987 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
989 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
991 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
996 KeQueryTickCount( &liCurrentTime);
998 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1000 if( pVolumeCB->ObjectInfoListHead == NULL &&
1001 pVolumeCB->DirectoryCB->OpenReferenceCount == 0 &&
1002 pVolumeCB->VolumeReferenceCount == 1 &&
1003 ( pVolumeCB->RootFcb == NULL ||
1004 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1005 pVolumeCB->ObjectInformation.ObjectReferenceCount == 0)
1008 if( pVolumeCB->RootFcb != NULL)
1011 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1014 AFSRemoveVolume( pVolumeCB);
1019 AFSReleaseResource( pVolumeCB->VolumeLock);
1022 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1024 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1026 pVolumeCB = pNextVolume;
1032 // Don't need this lock anymore now that we have a volume cb to work with
1035 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1038 // For now we only need the volume lock shared
1041 AFSConvertToShared( pVolumeCB->VolumeLock);
1043 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1047 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1051 bReleaseVolumeLock = TRUE;
1053 while( pCurrentObject != NULL)
1056 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1059 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1061 if( pNextObject == NULL &&
1062 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1065 pNextObject = &pVolumeCB->ObjectInformation;
1068 bVolumeObject = FALSE;
1075 bVolumeObject = TRUE;
1078 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1079 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1083 // If this object is deleted then remove it from the parent, if we can
1086 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1087 pCurrentObject->ObjectReferenceCount == 0 &&
1088 ( pCurrentObject->Fcb == NULL ||
1089 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1090 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1091 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1094 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1096 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1100 if( pCurrentObject->Fcb != NULL)
1103 AFSRemoveFcb( pCurrentObject->Fcb);
1106 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1109 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1112 AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1115 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1117 ExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1120 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1121 AFS_TRACE_LEVEL_VERBOSE,
1122 "AFSPrimaryWorker Deleting deleted object %08lX\n",
1125 AFSDeleteObjectInfo( pCurrentObject);
1127 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1129 pCurrentObject = pNextObject;
1136 bReleaseVolumeLock = FALSE;
1142 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1143 ( pCurrentObject->Fcb != NULL &&
1144 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1145 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1148 pCurrentObject = pNextObject;
1153 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1157 pCurrentObject = pNextObject;
1162 KeQueryTickCount( &liCurrentTime);
1164 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1166 while( pCurrentDirEntry != NULL)
1169 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1170 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1171 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1172 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1173 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1174 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1175 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1176 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1177 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1178 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1179 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1180 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1186 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1189 if( pCurrentDirEntry != NULL)
1192 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1194 pCurrentObject = pNextObject;
1199 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1201 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1204 // Now acquire the locks excl
1207 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1211 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1215 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1218 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1220 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1222 pCurrentObject = pNextObject;
1227 KeQueryTickCount( &liCurrentTime);
1229 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1231 while( pCurrentDirEntry != NULL)
1234 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1235 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1236 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1237 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1238 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1239 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1240 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1241 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1242 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1243 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1244 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1245 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1251 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1254 if( pCurrentDirEntry != NULL)
1257 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1259 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1261 pCurrentObject = pNextObject;
1266 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1268 while( pCurrentDirEntry != NULL)
1271 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1273 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1275 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1276 AFS_TRACE_LEVEL_VERBOSE,
1277 "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
1278 &pCurrentDirEntry->NameInformation.FileName,
1279 pCurrentChildObject);
1281 AFSDeleteDirEntry( pCurrentObject,
1284 if( pCurrentChildObject->ObjectReferenceCount == 0)
1287 if( pCurrentChildObject->Fcb != NULL)
1290 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1293 AFSCleanupFcb( pCurrentChildObject->Fcb,
1297 AFSRemoveFcb( pCurrentChildObject->Fcb);
1300 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1301 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1304 if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1307 AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1310 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1312 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1314 ExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1316 ExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1319 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1320 AFS_TRACE_LEVEL_VERBOSE,
1321 "AFSPrimaryWorker Deleting object %08lX\n",
1322 pCurrentChildObject);
1324 AFSDeleteObjectInfo( pCurrentChildObject);
1327 pCurrentDirEntry = pNextDirEntry;
1330 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1332 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1334 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1336 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1338 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1340 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1342 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1343 AFS_TRACE_LEVEL_VERBOSE,
1344 "AFSPrimaryWorker Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1345 pCurrentObject->FileId.Cell,
1346 pCurrentObject->FileId.Volume,
1347 pCurrentObject->FileId.Vnode,
1348 pCurrentObject->FileId.Unique);
1352 // Clear our enumerated flag on this object so we retrieve info again on next access
1355 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1357 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1362 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1364 bReleaseVolumeLock = FALSE;
1369 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1375 // Try to grab the volume lock again ... no problem if we don't
1378 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1382 bReleaseVolumeLock = FALSE;
1388 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1391 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1393 if( pCurrentObject == NULL &&
1394 pVolumeCB != AFSGlobalRoot)
1397 pCurrentObject = &pVolumeCB->ObjectInformation;
1403 pCurrentObject = NULL;
1408 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1411 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1412 pCurrentObject->ObjectReferenceCount == 0 &&
1413 ( pCurrentObject->Fcb == NULL ||
1414 pCurrentObject->Fcb->OpenReferenceCount == 0))
1417 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1419 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1423 if( pCurrentObject->Fcb != NULL)
1426 AFSCleanupFcb( pCurrentObject->Fcb,
1429 AFSRemoveFcb( pCurrentObject->Fcb);
1432 AFSDeleteObjectInfo( pCurrentObject);
1434 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1436 pCurrentObject = pNextObject;
1443 bReleaseVolumeLock = FALSE;
1448 else if( pCurrentObject->Fcb != NULL)
1451 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1453 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1457 AFSCleanupFcb( pCurrentObject->Fcb,
1460 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1462 pCurrentObject = pNextObject;
1469 bReleaseVolumeLock = FALSE;
1476 pCurrentObject = pNextObject;
1479 if( bReleaseVolumeLock)
1482 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1490 AFSReleaseResource( pVolumeCB->VolumeLock);
1492 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1495 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1498 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1500 } // worker thread loop
1502 KeCancelTimer( &Timer);
1504 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1505 AFS_TRACE_LEVEL_VERBOSE,
1506 "AFSPrimaryVolumeWorkerThread Exiting\n");
1508 if( InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) == 0)
1511 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1516 PsTerminateSystemThread( 0);
1522 AFSVolumeWorkerThread( IN PVOID Context)
1525 NTSTATUS ntStatus = STATUS_SUCCESS;
1526 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1527 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1528 AFSDeviceExt *pControlDeviceExt = NULL;
1529 AFSDeviceExt *pRDRDeviceExt = NULL;
1530 BOOLEAN exitThread = FALSE;
1531 LARGE_INTEGER DueTime;
1535 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1537 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1540 // Initialize the timer for the worker thread
1543 DueTime.QuadPart = -(5000);
1547 KeInitializeTimerEx( &Timer,
1548 SynchronizationTimer);
1550 KeSetTimerEx( &Timer,
1556 // Indicate that we are initialized and ready
1559 KeSetEvent( &pPoolContext->WorkerThreadReady,
1564 // Indicate we are initialized
1567 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1569 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1572 ntStatus = KeWaitForSingleObject( &Timer,
1578 if( !NT_SUCCESS( ntStatus))
1581 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1582 AFS_TRACE_LEVEL_ERROR,
1583 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1589 // If we are in shutdown mode and the dirty flag is clear then get out now
1592 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1598 } // worker thread loop
1600 KeCancelTimer( &Timer);
1602 if( InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount) == 0)
1605 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1610 PsTerminateSystemThread( 0);
1616 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1619 NTSTATUS ntStatus = STATUS_SUCCESS;
1620 AFSDeviceExt *pDevExt = NULL;
1622 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1624 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1625 AFS_TRACE_LEVEL_VERBOSE,
1626 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1627 &pDevExt->Specific.Library.QueueLock,
1628 PsGetCurrentThread());
1630 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1633 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1634 AFS_TRACE_LEVEL_VERBOSE,
1635 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1637 InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount));
1639 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1642 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1647 pDevExt->Specific.Library.QueueHead = WorkItem;
1650 WorkItem->next = NULL;
1651 pDevExt->Specific.Library.QueueTail = WorkItem;
1653 // indicate that the queue has nodes
1654 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1658 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1664 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1667 NTSTATUS ntStatus = STATUS_SUCCESS;
1668 AFSDeviceExt *pDevExt = NULL;
1670 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1672 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1673 AFS_TRACE_LEVEL_VERBOSE,
1674 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1675 &pDevExt->Specific.Library.IOQueueLock,
1676 PsGetCurrentThread());
1678 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1681 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1682 AFS_TRACE_LEVEL_VERBOSE,
1683 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1685 InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount));
1687 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1690 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1695 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1698 WorkItem->next = NULL;
1699 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1701 // indicate that the queue has nodes
1702 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1706 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1712 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1715 NTSTATUS ntStatus = STATUS_SUCCESS;
1716 AFSDeviceExt *pDevExt = NULL;
1718 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1720 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1721 AFS_TRACE_LEVEL_VERBOSE,
1722 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1723 &pDevExt->Specific.Library.QueueLock,
1724 PsGetCurrentThread());
1726 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1729 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1731 pDevExt->Specific.Library.QueueHead = WorkItem;
1733 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1734 AFS_TRACE_LEVEL_VERBOSE,
1735 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1737 InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount));
1740 // indicate that the queue has nodes
1743 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1747 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1756 NTSTATUS ntStatus = STATUS_SUCCESS;
1757 AFSWorkItem *pWorkItem = NULL;
1758 AFSDeviceExt *pDevExt = NULL;
1760 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1762 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1763 AFS_TRACE_LEVEL_VERBOSE,
1764 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1765 &pDevExt->Specific.Library.QueueLock,
1766 PsGetCurrentThread());
1768 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1771 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1774 pWorkItem = pDevExt->Specific.Library.QueueHead;
1776 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1777 AFS_TRACE_LEVEL_VERBOSE,
1778 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1780 InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount),
1781 PsGetCurrentThreadId());
1783 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1785 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1788 pDevExt->Specific.Library.QueueTail = NULL;
1790 KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
1795 KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
1798 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1804 AFSRemoveIOWorkItem()
1807 NTSTATUS ntStatus = STATUS_SUCCESS;
1808 AFSWorkItem *pWorkItem = NULL;
1809 AFSDeviceExt *pDevExt = NULL;
1811 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1813 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1814 AFS_TRACE_LEVEL_VERBOSE,
1815 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1816 &pDevExt->Specific.Library.IOQueueLock,
1817 PsGetCurrentThread());
1819 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1822 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
1825 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
1827 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1828 AFS_TRACE_LEVEL_VERBOSE,
1829 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1831 InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount),
1832 PsGetCurrentThreadId());
1834 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
1836 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
1839 pDevExt->Specific.Library.IOQueueTail = NULL;
1841 KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
1846 KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
1849 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1855 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
1858 NTSTATUS ntStatus = STATUS_SUCCESS;
1859 AFSDeviceExt *pDevExt = NULL;
1860 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1863 // Submit the work item to the worker
1866 ntStatus = AFSInsertWorkitem( WorkItem);
1872 // Sync request so block on the work item event
1875 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1886 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
1889 NTSTATUS ntStatus = STATUS_SUCCESS;
1890 AFSDeviceExt *pDevExt = NULL;
1891 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1894 // Submit the work item to the worker
1897 ntStatus = AFSInsertIOWorkitem( WorkItem);
1903 // Sync request so block on the work item event
1906 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1917 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
1920 NTSTATUS ntStatus = STATUS_SUCCESS;
1921 AFSDeviceExt *pDevExt = NULL;
1922 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1925 // Submit the work item to the worker
1928 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
1934 // Sync request so block on the work item event
1937 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1948 AFSQueueFlushExtents( IN AFSFcb *Fcb)
1951 NTSTATUS ntStatus = STATUS_SUCCESS;
1952 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1953 AFSWorkItem *pWorkItem = NULL;
1958 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1959 AFS_TRACE_LEVEL_VERBOSE,
1960 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
1961 Fcb->ObjectInformation->FileId.Cell,
1962 Fcb->ObjectInformation->FileId.Volume,
1963 Fcb->ObjectInformation->FileId.Vnode,
1964 Fcb->ObjectInformation->FileId.Unique);
1967 // Increment our flush count here just to keep the number of items in the
1968 // queue down. We'll decrement it just below.
1971 if( InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount) > 3)
1974 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1975 AFS_TRACE_LEVEL_VERBOSE,
1976 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
1977 Fcb->ObjectInformation->FileId.Cell,
1978 Fcb->ObjectInformation->FileId.Volume,
1979 Fcb->ObjectInformation->FileId.Vnode,
1980 Fcb->ObjectInformation->FileId.Unique);
1982 try_return( ntStatus);
1985 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1988 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1989 AFS_TRACE_LEVEL_ERROR,
1990 "AFSQueueFlushExtents Failing request, in shutdown\n");
1992 try_return( ntStatus = STATUS_TOO_LATE);
1996 // Allocate our request structure and send it to the worker
1999 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2000 sizeof( AFSWorkItem),
2003 if( pWorkItem == NULL)
2006 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2007 AFS_TRACE_LEVEL_ERROR,
2008 "AFSQueueFlushExtents Failed to allocate work item\n");
2010 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2013 RtlZeroMemory( pWorkItem,
2014 sizeof( AFSWorkItem));
2016 pWorkItem->Size = sizeof( AFSWorkItem);
2018 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2020 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2022 pWorkItem->Specific.Fcb.Fcb = Fcb;
2024 InterlockedIncrement( &Fcb->OpenReferenceCount);
2026 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2027 AFS_TRACE_LEVEL_VERBOSE,
2028 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2030 Fcb->OpenReferenceCount);
2032 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2033 AFS_TRACE_LEVEL_VERBOSE,
2034 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2036 Fcb->ObjectInformation->FileId.Cell,
2037 Fcb->ObjectInformation->FileId.Volume,
2038 Fcb->ObjectInformation->FileId.Vnode,
2039 Fcb->ObjectInformation->FileId.Unique);
2041 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2045 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2046 AFS_TRACE_LEVEL_VERBOSE,
2047 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2048 Fcb->ObjectInformation->FileId.Cell,
2049 Fcb->ObjectInformation->FileId.Volume,
2050 Fcb->ObjectInformation->FileId.Vnode,
2051 Fcb->ObjectInformation->FileId.Unique,
2055 // Remove the count we added above
2058 if( InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount) == 0)
2061 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2066 if( !NT_SUCCESS( ntStatus))
2069 if( pWorkItem != NULL)
2072 InterlockedDecrement( &Fcb->OpenReferenceCount);
2074 ExFreePool( pWorkItem);
2077 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2078 AFS_TRACE_LEVEL_ERROR,
2079 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2082 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2087 "EXCEPTION - AFSQueueFlushExtents\n");
2094 AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
2096 IN HANDLE CallerProcess)
2099 NTSTATUS ntStatus = STATUS_SUCCESS;
2100 AFSWorkItem *pWorkItem = NULL;
2105 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2106 AFS_TRACE_LEVEL_VERBOSE,
2107 "AFSQueueAsyncRead Queuing request for Irp %08lX\n",
2110 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2111 sizeof(AFSWorkItem),
2113 if (NULL == pWorkItem)
2116 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2117 AFS_TRACE_LEVEL_ERROR,
2118 "AFSQueueAsyncRead Failed to allocate work item\n");
2120 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2123 RtlZeroMemory( pWorkItem,
2124 sizeof(AFSWorkItem));
2126 pWorkItem->Size = sizeof( AFSWorkItem);
2128 pWorkItem->RequestType = AFS_WORK_ASYNCH_READ;
2130 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2132 pWorkItem->Specific.AsynchIo.Irp = Irp;
2134 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2136 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2137 AFS_TRACE_LEVEL_VERBOSE,
2138 "AFSQueueAsyncRead Workitem %08lX for Irp %08lX\n",
2142 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2146 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2147 AFS_TRACE_LEVEL_VERBOSE,
2148 "AFSQueueAsyncRead Request for Irp %08lX complete Status %08lX\n",
2152 if( !NT_SUCCESS( ntStatus))
2155 if( pWorkItem != NULL)
2158 ExFreePool( pWorkItem);
2161 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2162 AFS_TRACE_LEVEL_ERROR,
2163 "AFSQueueAsyncRead Failed to queue request Status %08lX\n", ntStatus);
2166 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2171 "EXCEPTION - AFSQueueAsyncRead\n");
2178 AFSQueueAsyncWrite( IN PDEVICE_OBJECT DeviceObject,
2180 IN HANDLE CallerProcess)
2183 NTSTATUS ntStatus = STATUS_SUCCESS;
2184 AFSWorkItem *pWorkItem = NULL;
2189 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2190 AFS_TRACE_LEVEL_VERBOSE,
2191 "AFSQueueAsyncWrite Queuing request for Irp %08lX\n",
2194 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2195 sizeof(AFSWorkItem),
2197 if (NULL == pWorkItem)
2200 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2201 AFS_TRACE_LEVEL_ERROR,
2202 "AFSQueueAsyncWrite Failed to allocate work item\n");
2204 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2207 RtlZeroMemory( pWorkItem,
2208 sizeof(AFSWorkItem));
2210 pWorkItem->Size = sizeof( AFSWorkItem);
2212 pWorkItem->RequestType = AFS_WORK_ASYNCH_WRITE;
2214 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2216 pWorkItem->Specific.AsynchIo.Irp = Irp;
2218 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2220 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2221 AFS_TRACE_LEVEL_VERBOSE,
2222 "AFSQueueAsyncWrite Workitem %08lX for Irp %08lX\n",
2226 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2230 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2231 AFS_TRACE_LEVEL_VERBOSE,
2232 "AFSQueueAsyncWrite Request for Irp %08lX complete Status %08lX\n",
2236 if( !NT_SUCCESS( ntStatus))
2239 if( pWorkItem != NULL)
2242 ExFreePool( pWorkItem);
2245 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2246 AFS_TRACE_LEVEL_ERROR,
2247 "AFSQueueAsyncWrite Failed to queue request Status %08lX\n", ntStatus);
2250 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2255 "EXCEPTION - AFSQueueAsyncWrite\n");
2262 AFSQueueGlobalRootEnumeration()
2265 NTSTATUS ntStatus = STATUS_SUCCESS;
2266 AFSWorkItem *pWorkItem = NULL;
2271 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2272 sizeof(AFSWorkItem),
2274 if (NULL == pWorkItem)
2277 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2278 AFS_TRACE_LEVEL_ERROR,
2279 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2281 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2284 RtlZeroMemory( pWorkItem,
2285 sizeof(AFSWorkItem));
2287 pWorkItem->Size = sizeof( AFSWorkItem);
2289 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2291 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2292 AFS_TRACE_LEVEL_VERBOSE,
2293 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2296 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2300 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2301 AFS_TRACE_LEVEL_VERBOSE,
2302 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2305 if( !NT_SUCCESS( ntStatus))
2308 if( pWorkItem != NULL)
2311 ExFreePool( pWorkItem);
2314 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2315 AFS_TRACE_LEVEL_ERROR,
2316 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2320 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2325 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2332 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2333 IN UCHAR FunctionCode,
2334 IN ULONG RequestFlags,
2335 IN AFSIoRun *IoRuns,
2337 IN AFSGatherIo *GatherIo)
2340 NTSTATUS ntStatus = STATUS_SUCCESS;
2341 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2342 AFSWorkItem *pWorkItem = NULL;
2347 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2350 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2351 AFS_TRACE_LEVEL_ERROR,
2352 "AFSQueueStartIos Failing request, in shutdown\n");
2354 try_return( ntStatus = STATUS_TOO_LATE);
2358 // Allocate our request structure and send it to the worker
2361 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2362 sizeof( AFSWorkItem),
2365 if( pWorkItem == NULL)
2368 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2369 AFS_TRACE_LEVEL_ERROR,
2370 "AFSQueueStartIos Failed to allocate work item\n");
2372 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2375 RtlZeroMemory( pWorkItem,
2376 sizeof( AFSWorkItem));
2378 KeInitializeEvent( &pWorkItem->Event,
2382 pWorkItem->Size = sizeof( AFSWorkItem);
2384 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2386 pWorkItem->RequestType = AFS_WORK_START_IOS;
2388 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2390 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2392 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2394 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2396 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2398 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2400 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2401 AFS_TRACE_LEVEL_VERBOSE,
2402 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2405 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2409 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2410 AFS_TRACE_LEVEL_VERBOSE,
2411 "AFSQueueStartIos Request complete Status %08lX\n",
2414 if( !NT_SUCCESS( ntStatus))
2417 if( pWorkItem != NULL)
2420 ExFreePool( pWorkItem);
2424 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2429 "EXCEPTION - AFSQueueStartIos\n");