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;
346 if( VolumeCB == AFSGlobalRoot)
349 pStartRoutine = AFSPrimaryVolumeWorkerThread;
354 pStartRoutine = AFSVolumeWorkerThread;
358 // Initialize the worker thread
361 KeInitializeEvent( &pWorker->WorkerThreadReady,
366 // Set the worker to process requests
369 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
375 ntStatus = PsCreateSystemThread( &hThread,
383 if( NT_SUCCESS( ntStatus))
386 ObReferenceObjectByHandle( hThread,
387 GENERIC_READ | GENERIC_WRITE,
390 (PVOID *)&pWorker->WorkerThreadObject,
393 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
399 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
404 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
415 // Function: AFSInitWorkerThread
419 // This function initializes a worker thread in the pool
423 // A status is returned for the function
427 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
428 IN PKSTART_ROUTINE WorkerRoutine)
431 NTSTATUS ntStatus = STATUS_SUCCESS;
435 // INitialize the worker signal thread
438 KeInitializeEvent( &PoolContext->WorkerThreadReady,
443 // Set the worker to process requests
446 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
452 ntStatus = PsCreateSystemThread( &Handle,
458 (void *)PoolContext);
460 if( NT_SUCCESS( ntStatus))
463 ObReferenceObjectByHandle( Handle,
464 GENERIC_READ | GENERIC_WRITE,
467 (PVOID *)&PoolContext->WorkerThreadObject,
470 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
483 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
486 NTSTATUS ntStatus = STATUS_SUCCESS;
487 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
489 if( pWorker->WorkerThreadObject != NULL &&
490 BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED))
494 // Clear the 'keep processing' flag
497 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
499 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
505 ObDereferenceObject( pWorker->WorkerThreadObject);
507 pWorker->WorkerThreadObject = NULL;
514 // Function: AFSShutdownWorkerThread
518 // This function shusdown a worker thread in the pool
522 // A status is returned for the function
526 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
529 NTSTATUS ntStatus = STATUS_SUCCESS;
530 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
532 if( PoolContext->WorkerThreadObject != NULL &&
533 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
537 // Clear the 'keep processing' flag
540 ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
543 // Wake up the thread if it is a sleep
546 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
550 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
556 ObDereferenceObject( PoolContext->WorkerThreadObject);
558 PoolContext->WorkerThreadObject = NULL;
565 // Function: AFSShutdownIOWorkerThread
569 // This function shutsdown an IO worker thread in the pool
573 // A status is returned for the function
577 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
580 NTSTATUS ntStatus = STATUS_SUCCESS;
581 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
583 if( PoolContext->WorkerThreadObject != NULL &&
584 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
588 // Clear the 'keep processing' flag
591 ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
594 // Wake up the thread if it is a sleep
597 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
601 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
607 ObDereferenceObject( PoolContext->WorkerThreadObject);
609 PoolContext->WorkerThreadObject = NULL;
616 // Function: AFSWorkerThread
620 // This is the worker thread entry point.
624 // A status is returned for the function
628 AFSWorkerThread( IN PVOID Context)
631 NTSTATUS ntStatus = STATUS_SUCCESS;
632 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
633 AFSWorkItem *pWorkItem;
634 BOOLEAN freeWorkItem = TRUE;
635 BOOLEAN exitThread = FALSE;
636 AFSDeviceExt *pLibraryDevExt = NULL;
639 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
642 // Indicate that we are initialized and ready
645 KeSetEvent( &pPoolContext->WorkerThreadReady,
651 // Indicate we are initialized
654 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
656 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
659 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
665 if( !NT_SUCCESS( ntStatus))
668 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
669 AFS_TRACE_LEVEL_ERROR,
670 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
675 pWorkItem = AFSRemoveWorkItem();
677 if( pWorkItem != NULL)
683 // Switch on the type of work item to process
686 switch( pWorkItem->RequestType)
689 case AFS_WORK_FLUSH_FCB:
692 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
693 &pWorkItem->AuthGroup);
695 if( !NT_SUCCESS( ntStatus))
698 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
699 &pWorkItem->AuthGroup);
702 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
704 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
709 case AFS_WORK_ASYNCH_READ:
712 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
714 (VOID) AFSCommonRead( pWorkItem->Specific.AsynchIo.Device,
715 pWorkItem->Specific.AsynchIo.Irp,
716 pWorkItem->Specific.AsynchIo.CallingProcess);
721 case AFS_WORK_ASYNCH_WRITE:
724 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
726 (VOID) AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
727 pWorkItem->Specific.AsynchIo.Irp,
728 pWorkItem->Specific.AsynchIo.CallingProcess);
732 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
735 AFSEnumerateGlobalRoot( NULL);
740 case AFS_WORK_INVALIDATE_OBJECT:
743 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
744 pWorkItem->Specific.Invalidate.InvalidateReason);
751 case AFS_WORK_START_IOS:
761 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
762 AFS_TRACE_LEVEL_ERROR,
763 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
771 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
775 } // worker thread loop
777 PsTerminateSystemThread( 0);
783 AFSIOWorkerThread( IN PVOID Context)
786 NTSTATUS ntStatus = STATUS_SUCCESS;
787 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
788 AFSWorkItem *pWorkItem;
789 BOOLEAN freeWorkItem = TRUE;
790 BOOLEAN exitThread = FALSE;
791 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
793 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
796 // Indicate that we are initialized and ready
799 KeSetEvent( &pPoolContext->WorkerThreadReady,
805 // Indicate we are initialized
808 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
810 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
813 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
819 if( !NT_SUCCESS( ntStatus))
822 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
823 AFS_TRACE_LEVEL_ERROR,
824 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
829 pWorkItem = AFSRemoveIOWorkItem();
831 if( pWorkItem != NULL)
837 // Switch on the type of work item to process
840 switch( pWorkItem->RequestType)
843 case AFS_WORK_START_IOS:
846 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
849 // The final status is in the gather io
852 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
853 pWorkItem->Specific.CacheAccess.FunctionCode,
854 pWorkItem->Specific.CacheAccess.RequestFlags,
855 pWorkItem->Specific.CacheAccess.IoRuns,
856 pWorkItem->Specific.CacheAccess.RunCount,
857 pWorkItem->Specific.CacheAccess.GatherIo);
860 // Regardless of the status we we do the complete - there may
862 // Decrement the count - setting the event if we were told
863 // to. This may trigger completion.
866 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
875 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
876 AFS_TRACE_LEVEL_ERROR,
877 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
885 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
889 } // worker thread loop
891 PsTerminateSystemThread( 0);
897 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
900 NTSTATUS ntStatus = STATUS_SUCCESS;
901 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
902 AFSDeviceExt *pControlDeviceExt = NULL;
903 AFSDeviceExt *pRDRDeviceExt = NULL;
904 BOOLEAN exitThread = FALSE;
905 LARGE_INTEGER DueTime;
908 BOOLEAN bFoundOpenEntry = FALSE;
909 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
910 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
911 BOOLEAN bReleaseVolumeLock = FALSE;
912 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
913 LARGE_INTEGER liCurrentTime;
914 BOOLEAN bVolumeObject = FALSE;
917 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
919 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
921 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
922 AFS_TRACE_LEVEL_VERBOSE,
923 "AFSPrimaryVolumeWorkerThread Initialized\n");
926 // Initialize the timer for the worker thread
929 DueTime.QuadPart = -(5000);
933 KeInitializeTimerEx( &Timer,
934 SynchronizationTimer);
936 KeSetTimerEx( &Timer,
942 // Indicate that we are initialized and ready
945 KeSetEvent( &pPoolContext->WorkerThreadReady,
950 // Indicate we are initialized
953 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
955 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
958 KeWaitForSingleObject( &Timer,
965 // This is the primary volume worker so it will traverse the volume list
966 // looking for cleanup or volumes requiring private workers
969 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
972 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
974 while( pVolumeCB != NULL)
977 if( pVolumeCB == AFSGlobalRoot ||
978 !AFSAcquireExcl( pVolumeCB->VolumeLock,
982 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
987 if( pVolumeCB->ObjectInfoListHead == NULL &&
988 pVolumeCB != AFSGlobalRoot)
991 AFSReleaseResource( pVolumeCB->VolumeLock);
993 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
995 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
998 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1001 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1005 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1007 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1009 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1014 KeQueryTickCount( &liCurrentTime);
1016 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1018 if( pVolumeCB->ObjectInfoListHead == NULL &&
1019 pVolumeCB->DirectoryCB->OpenReferenceCount == 0 &&
1020 pVolumeCB->VolumeReferenceCount == 1 &&
1021 ( pVolumeCB->RootFcb == NULL ||
1022 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1023 pVolumeCB->ObjectInformation.ObjectReferenceCount == 0)
1026 if( pVolumeCB->RootFcb != NULL)
1029 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1032 AFSRemoveVolume( pVolumeCB);
1037 AFSReleaseResource( pVolumeCB->VolumeLock);
1040 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1042 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1044 pVolumeCB = pNextVolume;
1050 // Don't need this lock anymore now that we have a volume cb to work with
1053 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1056 // For now we only need the volume lock shared
1059 AFSConvertToShared( pVolumeCB->VolumeLock);
1061 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1065 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1069 bReleaseVolumeLock = TRUE;
1071 while( pCurrentObject != NULL)
1074 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1077 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1079 if( pNextObject == NULL &&
1080 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1083 pNextObject = &pVolumeCB->ObjectInformation;
1086 bVolumeObject = FALSE;
1093 bVolumeObject = TRUE;
1096 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1097 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1101 // If this object is deleted then remove it from the parent, if we can
1104 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1105 pCurrentObject->ObjectReferenceCount == 0 &&
1106 ( pCurrentObject->Fcb == NULL ||
1107 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1108 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1109 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1112 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1114 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1118 if( pCurrentObject->Fcb != NULL)
1122 // Acquire and drop the Fcb resource to synchronize
1123 // with a potentially active AFSCleanup() which sets
1124 // the OpenReferenceCount to zero while holding the
1128 AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
1131 AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
1133 AFSRemoveFcb( pCurrentObject->Fcb);
1136 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1139 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1142 AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1145 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1147 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1149 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1151 AFSExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1154 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1155 AFS_TRACE_LEVEL_VERBOSE,
1156 "AFSPrimaryWorker Deleting deleted object %08lX\n",
1159 AFSDeleteObjectInfo( pCurrentObject);
1161 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1163 pCurrentObject = pNextObject;
1170 bReleaseVolumeLock = FALSE;
1176 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1177 ( pCurrentObject->Fcb != NULL &&
1178 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1179 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1182 pCurrentObject = pNextObject;
1187 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1191 pCurrentObject = pNextObject;
1196 KeQueryTickCount( &liCurrentTime);
1198 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1200 while( pCurrentDirEntry != NULL)
1203 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1204 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1205 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1206 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1207 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1208 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1209 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1210 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1211 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1212 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1213 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1214 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1220 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1223 if( pCurrentDirEntry != NULL)
1226 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1228 pCurrentObject = pNextObject;
1233 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1235 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1238 // Now acquire the locks excl
1241 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1245 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1249 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1252 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1254 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1256 pCurrentObject = pNextObject;
1261 KeQueryTickCount( &liCurrentTime);
1263 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1265 while( pCurrentDirEntry != NULL)
1268 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1269 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1270 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1271 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1272 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1273 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1274 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1275 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1276 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1277 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1278 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1279 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1285 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1288 if( pCurrentDirEntry != NULL)
1291 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1293 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1295 pCurrentObject = pNextObject;
1300 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1302 while( pCurrentDirEntry != NULL)
1305 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1307 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1309 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1310 AFS_TRACE_LEVEL_VERBOSE,
1311 "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
1312 &pCurrentDirEntry->NameInformation.FileName,
1313 pCurrentChildObject);
1315 AFSDeleteDirEntry( pCurrentObject,
1318 if( pCurrentChildObject->ObjectReferenceCount == 0)
1321 if( pCurrentChildObject->Fcb != NULL)
1324 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1327 AFSCleanupFcb( pCurrentChildObject->Fcb,
1332 // Acquire and drop the Fcb resource to synchronize
1333 // with a potentially active AFSCleanup() which sets
1334 // the OpenReferenceCount to zero while holding the
1338 AFSAcquireExcl( &pCurrentChildObject->Fcb->NPFcb->Resource,
1341 AFSReleaseResource( &pCurrentChildObject->Fcb->NPFcb->Resource);
1343 AFSRemoveFcb( pCurrentChildObject->Fcb);
1346 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1347 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1350 if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1353 AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1356 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1358 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1360 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1362 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1365 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1366 AFS_TRACE_LEVEL_VERBOSE,
1367 "AFSPrimaryWorker Deleting object %08lX\n",
1368 pCurrentChildObject);
1370 AFSDeleteObjectInfo( pCurrentChildObject);
1373 pCurrentDirEntry = pNextDirEntry;
1376 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1378 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1380 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1382 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1384 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1386 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1388 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1389 AFS_TRACE_LEVEL_VERBOSE,
1390 "AFSPrimaryWorker Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1391 pCurrentObject->FileId.Cell,
1392 pCurrentObject->FileId.Volume,
1393 pCurrentObject->FileId.Vnode,
1394 pCurrentObject->FileId.Unique);
1398 // Clear our enumerated flag on this object so we retrieve info again on next access
1401 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1403 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1408 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1410 bReleaseVolumeLock = FALSE;
1415 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1421 // Try to grab the volume lock again ... no problem if we don't
1424 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1428 bReleaseVolumeLock = FALSE;
1434 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1437 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1439 if( pCurrentObject == NULL &&
1440 pVolumeCB != AFSGlobalRoot)
1443 pCurrentObject = &pVolumeCB->ObjectInformation;
1449 pCurrentObject = NULL;
1454 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1457 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1458 pCurrentObject->ObjectReferenceCount == 0 &&
1459 ( pCurrentObject->Fcb == NULL ||
1460 pCurrentObject->Fcb->OpenReferenceCount == 0))
1463 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1465 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1469 if( pCurrentObject->Fcb != NULL)
1472 AFSCleanupFcb( pCurrentObject->Fcb,
1476 // Acquire and drop the Fcb resource to synchronize
1477 // with a potentially active AFSCleanup() which sets
1478 // the OpenReferenceCount to zero while holding the
1482 AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
1485 AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
1487 AFSRemoveFcb( pCurrentObject->Fcb);
1490 AFSDeleteObjectInfo( pCurrentObject);
1492 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1494 pCurrentObject = pNextObject;
1501 bReleaseVolumeLock = FALSE;
1506 else if( pCurrentObject->Fcb != NULL)
1509 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1511 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1515 AFSCleanupFcb( pCurrentObject->Fcb,
1518 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1520 pCurrentObject = pNextObject;
1527 bReleaseVolumeLock = FALSE;
1534 pCurrentObject = pNextObject;
1537 if( bReleaseVolumeLock)
1540 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1548 AFSReleaseResource( pVolumeCB->VolumeLock);
1550 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1553 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1556 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1558 } // worker thread loop
1560 KeCancelTimer( &Timer);
1562 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1563 AFS_TRACE_LEVEL_VERBOSE,
1564 "AFSPrimaryVolumeWorkerThread Exiting\n");
1566 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1571 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1576 PsTerminateSystemThread( 0);
1582 AFSVolumeWorkerThread( IN PVOID Context)
1585 NTSTATUS ntStatus = STATUS_SUCCESS;
1586 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1587 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1588 AFSDeviceExt *pControlDeviceExt = NULL;
1589 AFSDeviceExt *pRDRDeviceExt = NULL;
1590 BOOLEAN exitThread = FALSE;
1591 LARGE_INTEGER DueTime;
1596 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1598 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1601 // Initialize the timer for the worker thread
1604 DueTime.QuadPart = -(5000);
1608 KeInitializeTimerEx( &Timer,
1609 SynchronizationTimer);
1611 KeSetTimerEx( &Timer,
1617 // Indicate that we are initialized and ready
1620 KeSetEvent( &pPoolContext->WorkerThreadReady,
1625 // Indicate we are initialized
1628 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1630 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1633 ntStatus = KeWaitForSingleObject( &Timer,
1639 if( !NT_SUCCESS( ntStatus))
1642 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1643 AFS_TRACE_LEVEL_ERROR,
1644 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1650 // If we are in shutdown mode and the dirty flag is clear then get out now
1653 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1659 } // worker thread loop
1661 KeCancelTimer( &Timer);
1663 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1668 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1673 PsTerminateSystemThread( 0);
1679 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1682 NTSTATUS ntStatus = STATUS_SUCCESS;
1683 AFSDeviceExt *pDevExt = NULL;
1686 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1688 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1689 AFS_TRACE_LEVEL_VERBOSE,
1690 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1691 &pDevExt->Specific.Library.QueueLock,
1692 PsGetCurrentThread());
1694 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1697 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1699 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1700 AFS_TRACE_LEVEL_VERBOSE,
1701 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1705 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1708 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1713 pDevExt->Specific.Library.QueueHead = WorkItem;
1716 WorkItem->next = NULL;
1717 pDevExt->Specific.Library.QueueTail = WorkItem;
1719 // indicate that the queue has nodes
1720 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1724 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1730 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1733 NTSTATUS ntStatus = STATUS_SUCCESS;
1734 AFSDeviceExt *pDevExt = NULL;
1737 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1739 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1740 AFS_TRACE_LEVEL_VERBOSE,
1741 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1742 &pDevExt->Specific.Library.IOQueueLock,
1743 PsGetCurrentThread());
1745 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1748 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
1750 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1751 AFS_TRACE_LEVEL_VERBOSE,
1752 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1756 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1759 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1764 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1767 WorkItem->next = NULL;
1768 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1770 // indicate that the queue has nodes
1771 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1775 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1781 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1784 NTSTATUS ntStatus = STATUS_SUCCESS;
1785 AFSDeviceExt *pDevExt = NULL;
1788 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1790 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1791 AFS_TRACE_LEVEL_VERBOSE,
1792 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1793 &pDevExt->Specific.Library.QueueLock,
1794 PsGetCurrentThread());
1796 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1799 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1801 pDevExt->Specific.Library.QueueHead = WorkItem;
1803 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1805 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1806 AFS_TRACE_LEVEL_VERBOSE,
1807 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1812 // indicate that the queue has nodes
1815 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1819 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1828 NTSTATUS ntStatus = STATUS_SUCCESS;
1829 AFSWorkItem *pWorkItem = NULL;
1830 AFSDeviceExt *pDevExt = NULL;
1833 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1835 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1836 AFS_TRACE_LEVEL_VERBOSE,
1837 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1838 &pDevExt->Specific.Library.QueueLock,
1839 PsGetCurrentThread());
1841 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1844 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1847 pWorkItem = pDevExt->Specific.Library.QueueHead;
1849 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
1851 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1852 AFS_TRACE_LEVEL_VERBOSE,
1853 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1856 PsGetCurrentThreadId());
1858 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1860 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1863 pDevExt->Specific.Library.QueueTail = NULL;
1865 KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
1870 KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
1873 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1879 AFSRemoveIOWorkItem()
1882 NTSTATUS ntStatus = STATUS_SUCCESS;
1883 AFSWorkItem *pWorkItem = NULL;
1884 AFSDeviceExt *pDevExt = NULL;
1887 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1889 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1890 AFS_TRACE_LEVEL_VERBOSE,
1891 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1892 &pDevExt->Specific.Library.IOQueueLock,
1893 PsGetCurrentThread());
1895 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1898 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
1901 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
1903 lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
1905 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1906 AFS_TRACE_LEVEL_VERBOSE,
1907 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1910 PsGetCurrentThreadId());
1912 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
1914 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
1917 pDevExt->Specific.Library.IOQueueTail = NULL;
1919 KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
1924 KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
1927 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1933 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
1936 NTSTATUS ntStatus = STATUS_SUCCESS;
1937 AFSDeviceExt *pDevExt = NULL;
1938 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1941 // Submit the work item to the worker
1944 ntStatus = AFSInsertWorkitem( WorkItem);
1950 // Sync request so block on the work item event
1953 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1964 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
1967 NTSTATUS ntStatus = STATUS_SUCCESS;
1968 AFSDeviceExt *pDevExt = NULL;
1969 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
1972 // Submit the work item to the worker
1975 ntStatus = AFSInsertIOWorkitem( WorkItem);
1981 // Sync request so block on the work item event
1984 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
1995 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
1998 NTSTATUS ntStatus = STATUS_SUCCESS;
1999 AFSDeviceExt *pDevExt = NULL;
2000 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2003 // Submit the work item to the worker
2006 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2012 // Sync request so block on the work item event
2015 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2026 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2030 NTSTATUS ntStatus = STATUS_SUCCESS;
2031 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2032 AFSWorkItem *pWorkItem = NULL;
2038 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2039 AFS_TRACE_LEVEL_VERBOSE,
2040 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2041 Fcb->ObjectInformation->FileId.Cell,
2042 Fcb->ObjectInformation->FileId.Volume,
2043 Fcb->ObjectInformation->FileId.Vnode,
2044 Fcb->ObjectInformation->FileId.Unique);
2047 // Increment our flush count here just to keep the number of items in the
2048 // queue down. We'll decrement it just below.
2051 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2056 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2057 AFS_TRACE_LEVEL_VERBOSE,
2058 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2059 Fcb->ObjectInformation->FileId.Cell,
2060 Fcb->ObjectInformation->FileId.Volume,
2061 Fcb->ObjectInformation->FileId.Vnode,
2062 Fcb->ObjectInformation->FileId.Unique);
2064 try_return( ntStatus);
2067 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2070 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2071 AFS_TRACE_LEVEL_ERROR,
2072 "AFSQueueFlushExtents Failing request, in shutdown\n");
2074 try_return( ntStatus = STATUS_TOO_LATE);
2078 // Allocate our request structure and send it to the worker
2081 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2082 sizeof( AFSWorkItem),
2085 if( pWorkItem == NULL)
2088 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2089 AFS_TRACE_LEVEL_ERROR,
2090 "AFSQueueFlushExtents Failed to allocate work item\n");
2092 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2095 RtlZeroMemory( pWorkItem,
2096 sizeof( AFSWorkItem));
2098 pWorkItem->Size = sizeof( AFSWorkItem);
2100 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2102 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2104 RtlCopyMemory( &pWorkItem->AuthGroup,
2108 pWorkItem->Specific.Fcb.Fcb = Fcb;
2110 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2112 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2113 AFS_TRACE_LEVEL_VERBOSE,
2114 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2118 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2119 AFS_TRACE_LEVEL_VERBOSE,
2120 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2122 Fcb->ObjectInformation->FileId.Cell,
2123 Fcb->ObjectInformation->FileId.Volume,
2124 Fcb->ObjectInformation->FileId.Vnode,
2125 Fcb->ObjectInformation->FileId.Unique);
2127 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2131 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2132 AFS_TRACE_LEVEL_VERBOSE,
2133 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2134 Fcb->ObjectInformation->FileId.Cell,
2135 Fcb->ObjectInformation->FileId.Volume,
2136 Fcb->ObjectInformation->FileId.Vnode,
2137 Fcb->ObjectInformation->FileId.Unique,
2141 // Remove the count we added above
2144 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2149 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2154 if( !NT_SUCCESS( ntStatus))
2157 if( pWorkItem != NULL)
2160 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2162 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2165 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2166 AFS_TRACE_LEVEL_ERROR,
2167 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2170 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2175 "EXCEPTION - AFSQueueFlushExtents\n");
2182 AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
2184 IN HANDLE CallerProcess)
2187 NTSTATUS ntStatus = STATUS_SUCCESS;
2188 AFSWorkItem *pWorkItem = NULL;
2193 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2194 AFS_TRACE_LEVEL_VERBOSE,
2195 "AFSQueueAsyncRead Queuing request for Irp %08lX\n",
2198 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2199 sizeof(AFSWorkItem),
2201 if (NULL == pWorkItem)
2204 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2205 AFS_TRACE_LEVEL_ERROR,
2206 "AFSQueueAsyncRead Failed to allocate work item\n");
2208 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2211 RtlZeroMemory( pWorkItem,
2212 sizeof(AFSWorkItem));
2214 pWorkItem->Size = sizeof( AFSWorkItem);
2216 pWorkItem->RequestType = AFS_WORK_ASYNCH_READ;
2218 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2220 pWorkItem->Specific.AsynchIo.Irp = Irp;
2222 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2224 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2225 AFS_TRACE_LEVEL_VERBOSE,
2226 "AFSQueueAsyncRead Workitem %08lX for Irp %08lX\n",
2230 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2234 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2235 AFS_TRACE_LEVEL_VERBOSE,
2236 "AFSQueueAsyncRead Request for Irp %08lX complete Status %08lX\n",
2240 if( !NT_SUCCESS( ntStatus))
2243 if( pWorkItem != NULL)
2246 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2249 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2250 AFS_TRACE_LEVEL_ERROR,
2251 "AFSQueueAsyncRead Failed to queue request Status %08lX\n", ntStatus);
2254 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2259 "EXCEPTION - AFSQueueAsyncRead\n");
2266 AFSQueueAsyncWrite( IN PDEVICE_OBJECT DeviceObject,
2268 IN HANDLE CallerProcess)
2271 NTSTATUS ntStatus = STATUS_SUCCESS;
2272 AFSWorkItem *pWorkItem = NULL;
2277 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2278 AFS_TRACE_LEVEL_VERBOSE,
2279 "AFSQueueAsyncWrite Queuing request for Irp %08lX\n",
2282 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2283 sizeof(AFSWorkItem),
2285 if (NULL == pWorkItem)
2288 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2289 AFS_TRACE_LEVEL_ERROR,
2290 "AFSQueueAsyncWrite Failed to allocate work item\n");
2292 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2295 RtlZeroMemory( pWorkItem,
2296 sizeof(AFSWorkItem));
2298 pWorkItem->Size = sizeof( AFSWorkItem);
2300 pWorkItem->RequestType = AFS_WORK_ASYNCH_WRITE;
2302 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2304 pWorkItem->Specific.AsynchIo.Irp = Irp;
2306 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2308 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2309 AFS_TRACE_LEVEL_VERBOSE,
2310 "AFSQueueAsyncWrite Workitem %08lX for Irp %08lX\n",
2314 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2318 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2319 AFS_TRACE_LEVEL_VERBOSE,
2320 "AFSQueueAsyncWrite Request for Irp %08lX complete Status %08lX\n",
2324 if( !NT_SUCCESS( ntStatus))
2327 if( pWorkItem != NULL)
2330 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2333 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2334 AFS_TRACE_LEVEL_ERROR,
2335 "AFSQueueAsyncWrite Failed to queue request Status %08lX\n", ntStatus);
2338 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2343 "EXCEPTION - AFSQueueAsyncWrite\n");
2350 AFSQueueGlobalRootEnumeration()
2353 NTSTATUS ntStatus = STATUS_SUCCESS;
2354 AFSWorkItem *pWorkItem = NULL;
2359 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2360 sizeof(AFSWorkItem),
2362 if (NULL == pWorkItem)
2365 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2366 AFS_TRACE_LEVEL_ERROR,
2367 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2369 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2372 RtlZeroMemory( pWorkItem,
2373 sizeof(AFSWorkItem));
2375 pWorkItem->Size = sizeof( AFSWorkItem);
2377 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2379 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2380 AFS_TRACE_LEVEL_VERBOSE,
2381 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2384 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2388 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2389 AFS_TRACE_LEVEL_VERBOSE,
2390 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2393 if( !NT_SUCCESS( ntStatus))
2396 if( pWorkItem != NULL)
2399 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2402 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2403 AFS_TRACE_LEVEL_ERROR,
2404 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2408 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2413 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2420 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2421 IN UCHAR FunctionCode,
2422 IN ULONG RequestFlags,
2423 IN AFSIoRun *IoRuns,
2425 IN AFSGatherIo *GatherIo)
2428 NTSTATUS ntStatus = STATUS_SUCCESS;
2429 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2430 AFSWorkItem *pWorkItem = NULL;
2435 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2438 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2439 AFS_TRACE_LEVEL_ERROR,
2440 "AFSQueueStartIos Failing request, in shutdown\n");
2442 try_return( ntStatus = STATUS_TOO_LATE);
2446 // Allocate our request structure and send it to the worker
2449 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2450 sizeof( AFSWorkItem),
2453 if( pWorkItem == NULL)
2456 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2457 AFS_TRACE_LEVEL_ERROR,
2458 "AFSQueueStartIos Failed to allocate work item\n");
2460 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2463 RtlZeroMemory( pWorkItem,
2464 sizeof( AFSWorkItem));
2466 KeInitializeEvent( &pWorkItem->Event,
2470 pWorkItem->Size = sizeof( AFSWorkItem);
2472 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2474 pWorkItem->RequestType = AFS_WORK_START_IOS;
2476 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2478 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2480 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2482 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2484 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2486 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2488 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2489 AFS_TRACE_LEVEL_VERBOSE,
2490 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2493 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2497 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2498 AFS_TRACE_LEVEL_VERBOSE,
2499 "AFSQueueStartIos Request complete Status %08lX\n",
2502 if( !NT_SUCCESS( ntStatus))
2505 if( pWorkItem != NULL)
2508 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2512 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2517 "EXCEPTION - AFSQueueStartIos\n");
2524 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2525 IN ULONG InvalidateReason)
2528 NTSTATUS ntStatus = STATUS_SUCCESS;
2529 AFSWorkItem *pWorkItem = NULL;
2534 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2535 sizeof(AFSWorkItem),
2537 if (NULL == pWorkItem)
2540 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2541 AFS_TRACE_LEVEL_ERROR,
2542 "AFSQueueInvalidateObject Failed to allocate work item\n");
2544 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2547 RtlZeroMemory( pWorkItem,
2548 sizeof(AFSWorkItem));
2550 pWorkItem->Size = sizeof( AFSWorkItem);
2552 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2554 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2556 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2558 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2559 AFS_TRACE_LEVEL_VERBOSE,
2560 "AFSQueueInvalidateObject Workitem %08lX\n",
2563 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2567 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2568 AFS_TRACE_LEVEL_VERBOSE,
2569 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2572 if( !NT_SUCCESS( ntStatus))
2575 if( pWorkItem != NULL)
2577 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2580 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2581 AFS_TRACE_LEVEL_ERROR,
2582 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2586 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2591 "EXCEPTION - AFSQueueInvalidateObject\n");