2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSWorker.cpp
39 #include "AFSCommon.h"
42 // Function: AFSInitializeWorkerPool
46 // This function initializes the worker thread pool
50 // A status is returned for the function
54 AFSInitializeWorkerPool()
57 NTSTATUS ntStatus = STATUS_SUCCESS;
58 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
59 AFSDeviceExt *pDevExt = NULL;
64 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
67 // Initialize the worker threads.
70 pDevExt->Specific.Library.WorkerCount = 0;
72 KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
77 // Initialize the queue resource
80 ExInitializeResourceLite( &pDevExt->Specific.Library.QueueLock);
82 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
85 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
86 sizeof( AFSWorkQueueContext),
89 if( pCurrentWorker == NULL)
92 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
93 AFS_TRACE_LEVEL_ERROR,
94 "AFSInitializeWorkerPool Failed to allocate worker context\n");
96 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
101 RtlZeroMemory( pCurrentWorker,
102 sizeof( AFSWorkQueueContext));
104 ntStatus = AFSInitWorkerThread( pCurrentWorker,
105 (PKSTART_ROUTINE)AFSWorkerThread);
107 if( !NT_SUCCESS( ntStatus))
110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
111 AFS_TRACE_LEVEL_ERROR,
112 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
114 ExFreePool( pCurrentWorker);
119 if( pDevExt->Specific.Library.PoolHead == NULL)
122 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
127 pLastWorker->fLink = pCurrentWorker;
130 pLastWorker = pCurrentWorker;
132 pDevExt->Specific.Library.WorkerCount++;
136 // If there was a failure but there is at least one worker, then go with it.
139 if( !NT_SUCCESS( ntStatus) &&
140 pDevExt->Specific.Library.WorkerCount == 0)
143 try_return( ntStatus);
146 ntStatus = STATUS_SUCCESS;
149 // Now our IO Worker queue
152 pDevExt->Specific.Library.IOWorkerCount = 0;
154 KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
155 SynchronizationEvent,
159 // Initialize the queue resource
162 ExInitializeResourceLite( &pDevExt->Specific.Library.IOQueueLock);
164 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
167 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
168 sizeof( AFSWorkQueueContext),
171 if( pCurrentWorker == NULL)
174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
178 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
183 RtlZeroMemory( pCurrentWorker,
184 sizeof( AFSWorkQueueContext));
186 ntStatus = AFSInitWorkerThread( pCurrentWorker,
187 (PKSTART_ROUTINE)AFSIOWorkerThread);
189 if( !NT_SUCCESS( ntStatus))
192 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
193 AFS_TRACE_LEVEL_ERROR,
194 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
196 ExFreePool( pCurrentWorker);
201 if( pDevExt->Specific.Library.IOPoolHead == NULL)
204 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
209 pLastWorker->fLink = pCurrentWorker;
212 pLastWorker = pCurrentWorker;
214 pDevExt->Specific.Library.IOWorkerCount++;
218 // If there was a failure but there is at least one worker, then go with it.
221 if( !NT_SUCCESS( ntStatus) &&
222 pDevExt->Specific.Library.IOWorkerCount == 0)
225 try_return( ntStatus);
230 if( !NT_SUCCESS( ntStatus))
234 // Failed to initialize the pool so tear it down
237 AFSRemoveWorkerPool();
245 // Function: AFSRemoveWorkerPool
249 // This function tears down the worker thread pool
253 // A status is returned for the function
257 AFSRemoveWorkerPool()
260 NTSTATUS ntStatus = STATUS_SUCCESS;
262 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
263 AFSDeviceExt *pDevExt = NULL;
265 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
268 // Loop through the workers shutting them down in two stages.
269 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
270 // stop processing requests. Second, call AFSShutdownWorkerThread()
271 // to wake the workers and wait for them to exit.
274 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
276 while( index < pDevExt->Specific.Library.WorkerCount)
279 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
281 pCurrentWorker = pCurrentWorker->fLink;
283 if ( pCurrentWorker == NULL)
292 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
296 while( index < pDevExt->Specific.Library.WorkerCount)
299 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
301 pNextWorker = pCurrentWorker->fLink;
303 ExFreePool( pCurrentWorker);
305 pCurrentWorker = pNextWorker;
307 if( pCurrentWorker == NULL)
316 pDevExt->Specific.Library.PoolHead = NULL;
318 ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
321 // Loop through the IO workers shutting them down in two stages.
322 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
323 // stop processing requests. Second, call AFSShutdownWorkerThread()
324 // to wake the workers and wait for them to exit.
327 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
331 while( index < pDevExt->Specific.Library.IOWorkerCount)
334 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
336 pCurrentWorker = pCurrentWorker->fLink;
338 if ( pCurrentWorker == NULL)
347 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
351 while( index < pDevExt->Specific.Library.IOWorkerCount)
354 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
356 pNextWorker = pCurrentWorker->fLink;
358 ExFreePool( pCurrentWorker);
360 pCurrentWorker = pNextWorker;
362 if( pCurrentWorker == NULL)
371 pDevExt->Specific.Library.IOPoolHead = NULL;
373 ExDeleteResourceLite( &pDevExt->Specific.Library.IOQueueLock);
379 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
382 NTSTATUS ntStatus = STATUS_SUCCESS;
383 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
385 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
386 PKSTART_ROUTINE pStartRoutine = NULL;
392 if( VolumeCB == AFSGlobalRoot)
395 pStartRoutine = AFSPrimaryVolumeWorkerThread;
400 pStartRoutine = AFSVolumeWorkerThread;
404 // Initialize the worker thread
407 KeInitializeEvent( &pWorker->WorkerThreadReady,
412 // Set the worker to process requests
415 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
421 ntStatus = PsCreateSystemThread( &hThread,
429 if( NT_SUCCESS( ntStatus))
432 ObReferenceObjectByHandle( hThread,
433 GENERIC_READ | GENERIC_WRITE,
436 (PVOID *)&pWorker->WorkerThreadObject,
439 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
445 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
450 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
461 // Function: AFSInitWorkerThread
465 // This function initializes a worker thread in the pool
469 // A status is returned for the function
473 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
474 IN PKSTART_ROUTINE WorkerRoutine)
477 NTSTATUS ntStatus = STATUS_SUCCESS;
481 // INitialize the worker signal thread
484 KeInitializeEvent( &PoolContext->WorkerThreadReady,
489 // Set the worker to process requests
492 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
498 ntStatus = PsCreateSystemThread( &Handle,
504 (void *)PoolContext);
506 if( NT_SUCCESS( ntStatus))
509 ObReferenceObjectByHandle( Handle,
510 GENERIC_READ | GENERIC_WRITE,
513 (PVOID *)&PoolContext->WorkerThreadObject,
516 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
529 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
532 NTSTATUS ntStatus = STATUS_SUCCESS;
533 AFSWorkQueueContext *pWorker = &VolumeCB->VolumeWorkerContext;
535 if( pWorker->WorkerThreadObject != NULL &&
536 BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED))
540 // Clear the 'keep processing' flag
543 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
545 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
551 ObDereferenceObject( pWorker->WorkerThreadObject);
553 pWorker->WorkerThreadObject = NULL;
560 // Function: AFSShutdownWorkerThread
564 // This function shutsdown a worker thread in the pool
568 // A status is returned for the function
572 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
575 NTSTATUS ntStatus = STATUS_SUCCESS;
576 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
578 if( PoolContext->WorkerThreadObject != NULL &&
579 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
583 // Wake up the thread if it is a sleep
586 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
590 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
596 ObDereferenceObject( PoolContext->WorkerThreadObject);
598 PoolContext->WorkerThreadObject = NULL;
605 // Function: AFSShutdownIOWorkerThread
609 // This function shutsdown an IO worker thread in the pool
613 // A status is returned for the function
617 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
620 NTSTATUS ntStatus = STATUS_SUCCESS;
621 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
623 if( PoolContext->WorkerThreadObject != NULL &&
624 BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED))
628 // Wake up the thread if it is a sleep
631 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
635 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
641 ObDereferenceObject( PoolContext->WorkerThreadObject);
643 PoolContext->WorkerThreadObject = NULL;
650 // Function: AFSWorkerThread
654 // This is the worker thread entry point.
658 // A status is returned for the function
662 AFSWorkerThread( IN PVOID Context)
665 NTSTATUS ntStatus = STATUS_SUCCESS;
666 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
667 AFSWorkItem *pWorkItem;
668 BOOLEAN freeWorkItem = TRUE;
669 AFSDeviceExt *pLibraryDevExt = NULL;
672 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
675 // Indicate that we are initialized and ready
678 KeSetEvent( &pPoolContext->WorkerThreadReady,
683 // Indicate we are initialized
686 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
688 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
694 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
697 if( !NT_SUCCESS( ntStatus))
700 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
701 AFS_TRACE_LEVEL_ERROR,
702 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
707 pWorkItem = AFSRemoveWorkItem();
709 if( pWorkItem != NULL)
715 // Switch on the type of work item to process
718 switch( pWorkItem->RequestType)
721 case AFS_WORK_FLUSH_FCB:
724 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
725 &pWorkItem->AuthGroup);
727 if( !NT_SUCCESS( ntStatus))
730 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
731 &pWorkItem->AuthGroup);
734 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
736 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
741 case AFS_WORK_ASYNCH_READ:
744 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
746 (VOID) AFSCommonRead( pWorkItem->Specific.AsynchIo.Device,
747 pWorkItem->Specific.AsynchIo.Irp,
748 pWorkItem->Specific.AsynchIo.CallingProcess);
753 case AFS_WORK_ASYNCH_WRITE:
756 ASSERT( pWorkItem->Specific.AsynchIo.CallingProcess != NULL);
758 (VOID) AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
759 pWorkItem->Specific.AsynchIo.Irp,
760 pWorkItem->Specific.AsynchIo.CallingProcess);
764 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
767 AFSEnumerateGlobalRoot( NULL);
772 case AFS_WORK_INVALIDATE_OBJECT:
775 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
776 pWorkItem->Specific.Invalidate.InvalidateReason);
783 case AFS_WORK_START_IOS:
793 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
794 AFS_TRACE_LEVEL_ERROR,
795 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
803 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
808 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
814 } // worker thread loop
816 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
818 // Wake up another worker so they too can exit
820 KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
824 PsTerminateSystemThread( 0);
830 AFSIOWorkerThread( IN PVOID Context)
833 NTSTATUS ntStatus = STATUS_SUCCESS;
834 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
835 AFSWorkItem *pWorkItem;
836 BOOLEAN freeWorkItem = TRUE;
837 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
839 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
842 // Indicate that we are initialized and ready
845 KeSetEvent( &pPoolContext->WorkerThreadReady,
851 // Indicate we are initialized
854 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
856 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
862 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
865 if( !NT_SUCCESS( ntStatus))
868 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
869 AFS_TRACE_LEVEL_ERROR,
870 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
875 pWorkItem = AFSRemoveIOWorkItem();
877 if( pWorkItem != NULL)
883 // Switch on the type of work item to process
886 switch( pWorkItem->RequestType)
889 case AFS_WORK_START_IOS:
892 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
895 // The final status is in the gather io
898 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
899 pWorkItem->Specific.CacheAccess.FunctionCode,
900 pWorkItem->Specific.CacheAccess.RequestFlags,
901 pWorkItem->Specific.CacheAccess.IoRuns,
902 pWorkItem->Specific.CacheAccess.RunCount,
903 pWorkItem->Specific.CacheAccess.GatherIo);
906 // Regardless of the status we we do the complete - there may
908 // Decrement the count - setting the event if we were told
909 // to. This may trigger completion.
912 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
922 AFS_TRACE_LEVEL_ERROR,
923 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
931 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
936 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
942 } // worker thread loop
944 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
946 // Wake up another IOWorker so they too can exit
948 KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
952 PsTerminateSystemThread( 0);
958 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
961 NTSTATUS ntStatus = STATUS_SUCCESS;
962 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
963 AFSDeviceExt *pControlDeviceExt = NULL;
964 AFSDeviceExt *pRDRDeviceExt = NULL;
965 LARGE_INTEGER DueTime;
968 BOOLEAN bFoundOpenEntry = FALSE;
969 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL, *pCurrentChildObject = NULL;
970 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
971 BOOLEAN bReleaseVolumeLock = FALSE;
972 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
973 LARGE_INTEGER liCurrentTime;
974 BOOLEAN bVolumeObject = FALSE;
977 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
979 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
981 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
982 AFS_TRACE_LEVEL_VERBOSE,
983 "AFSPrimaryVolumeWorkerThread Initialized\n");
986 // Initialize the timer for the worker thread
989 DueTime.QuadPart = -(5000);
993 KeInitializeTimerEx( &Timer,
994 SynchronizationTimer);
996 KeSetTimerEx( &Timer,
1002 // Indicate that we are initialized and ready
1005 KeSetEvent( &pPoolContext->WorkerThreadReady,
1010 // Indicate we are initialized
1013 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1015 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1018 KeWaitForSingleObject( &Timer,
1025 // This is the primary volume worker so it will traverse the volume list
1026 // looking for cleanup or volumes requiring private workers
1029 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1032 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1034 while( pVolumeCB != NULL)
1037 if( pVolumeCB == AFSGlobalRoot ||
1038 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1042 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1047 if( pVolumeCB->ObjectInfoListHead == NULL &&
1048 pVolumeCB != AFSGlobalRoot)
1051 AFSReleaseResource( pVolumeCB->VolumeLock);
1053 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1055 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1058 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1061 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1065 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1067 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1069 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1074 KeQueryTickCount( &liCurrentTime);
1076 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1078 if( pVolumeCB->ObjectInfoListHead == NULL &&
1079 pVolumeCB->DirectoryCB->OpenReferenceCount == 0 &&
1080 pVolumeCB->VolumeReferenceCount == 1 &&
1081 ( pVolumeCB->RootFcb == NULL ||
1082 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1083 pVolumeCB->ObjectInformation.ObjectReferenceCount == 0)
1086 if( pVolumeCB->RootFcb != NULL)
1089 AFSRemoveRootFcb( pVolumeCB->RootFcb);
1092 AFSRemoveVolume( pVolumeCB);
1097 AFSReleaseResource( pVolumeCB->VolumeLock);
1100 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1102 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1104 pVolumeCB = pNextVolume;
1110 // Don't need this lock anymore now that we have a volume cb to work with
1113 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1116 // For now we only need the volume lock shared
1119 AFSConvertToShared( pVolumeCB->VolumeLock);
1121 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1125 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1129 bReleaseVolumeLock = TRUE;
1131 while( pCurrentObject != NULL)
1134 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1137 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1139 if( pNextObject == NULL &&
1140 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1143 pNextObject = &pVolumeCB->ObjectInformation;
1146 bVolumeObject = FALSE;
1153 bVolumeObject = TRUE;
1156 if( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1157 !BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN)) // If we are in shutdown mode skip directories
1161 // If this object is deleted then remove it from the parent, if we can
1164 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1165 pCurrentObject->ObjectReferenceCount == 0 &&
1166 ( pCurrentObject->Fcb == NULL ||
1167 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1168 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1169 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1172 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1174 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1178 if( pCurrentObject->Fcb != NULL)
1182 // Acquire and drop the Fcb resource to synchronize
1183 // with a potentially active AFSCleanup() which sets
1184 // the OpenReferenceCount to zero while holding the
1188 AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
1191 AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
1193 AFSRemoveFcb( pCurrentObject->Fcb);
1196 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1199 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1202 AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1205 AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1207 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1209 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1211 AFSExFreePool( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1214 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1215 AFS_TRACE_LEVEL_VERBOSE,
1216 "AFSPrimaryWorker Deleting deleted object %08lX\n",
1219 AFSDeleteObjectInfo( pCurrentObject);
1221 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1223 pCurrentObject = pNextObject;
1230 bReleaseVolumeLock = FALSE;
1236 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1237 ( pCurrentObject->Fcb != NULL &&
1238 pCurrentObject->Fcb->OpenReferenceCount > 0) ||
1239 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL)
1242 pCurrentObject = pNextObject;
1247 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1251 pCurrentObject = pNextObject;
1256 KeQueryTickCount( &liCurrentTime);
1258 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1260 while( pCurrentDirEntry != NULL)
1263 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1264 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1265 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1266 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1267 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1268 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1269 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1270 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1271 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1272 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1273 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1274 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1280 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1283 if( pCurrentDirEntry != NULL)
1286 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1288 pCurrentObject = pNextObject;
1293 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1295 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1298 // Now acquire the locks excl
1301 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1305 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1309 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1312 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1314 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1316 pCurrentObject = pNextObject;
1321 KeQueryTickCount( &liCurrentTime);
1323 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1325 while( pCurrentDirEntry != NULL)
1328 if( pCurrentDirEntry->OpenReferenceCount > 0 ||
1329 ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1330 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0) ||
1331 liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1332 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1333 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart ||
1334 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY &&
1335 ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL ||
1336 pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)) ||
1337 ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE &&
1338 pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1339 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0))
1345 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1348 if( pCurrentDirEntry != NULL)
1351 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1353 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1355 pCurrentObject = pNextObject;
1360 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1362 while( pCurrentDirEntry != NULL)
1365 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1367 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
1369 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1370 AFS_TRACE_LEVEL_VERBOSE,
1371 "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
1372 &pCurrentDirEntry->NameInformation.FileName,
1373 pCurrentChildObject);
1375 AFSDeleteDirEntry( pCurrentObject,
1378 if( pCurrentChildObject->ObjectReferenceCount == 0)
1381 if( pCurrentChildObject->Fcb != NULL)
1384 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
1387 AFSCleanupFcb( pCurrentChildObject->Fcb,
1392 // Acquire and drop the Fcb resource to synchronize
1393 // with a potentially active AFSCleanup() which sets
1394 // the OpenReferenceCount to zero while holding the
1398 AFSAcquireExcl( &pCurrentChildObject->Fcb->NPFcb->Resource,
1401 AFSReleaseResource( &pCurrentChildObject->Fcb->NPFcb->Resource);
1403 AFSRemoveFcb( pCurrentChildObject->Fcb);
1406 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1407 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1410 if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
1413 AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1416 AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1418 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1420 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged);
1422 AFSExFreePool( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1425 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1426 AFS_TRACE_LEVEL_VERBOSE,
1427 "AFSPrimaryWorker Deleting object %08lX\n",
1428 pCurrentChildObject);
1430 AFSDeleteObjectInfo( pCurrentChildObject);
1433 pCurrentDirEntry = pNextDirEntry;
1436 pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
1438 pCurrentObject->Specific.Directory.DirectoryNodeListTail = NULL;
1440 pCurrentObject->Specific.Directory.ShortNameTree = NULL;
1442 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseSensitiveTreeHead = NULL;
1444 pCurrentObject->Specific.Directory.DirectoryNodeHdr.CaseInsensitiveTreeHead = NULL;
1446 pCurrentObject->Specific.Directory.DirectoryNodeCount = 0;
1448 AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
1449 AFS_TRACE_LEVEL_VERBOSE,
1450 "AFSPrimaryWorker Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
1451 pCurrentObject->FileId.Cell,
1452 pCurrentObject->FileId.Volume,
1453 pCurrentObject->FileId.Vnode,
1454 pCurrentObject->FileId.Unique);
1458 // Clear our enumerated flag on this object so we retrieve info again on next access
1461 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1463 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1468 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1470 bReleaseVolumeLock = FALSE;
1475 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1481 // Try to grab the volume lock again ... no problem if we don't
1484 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1488 bReleaseVolumeLock = FALSE;
1494 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1497 pCurrentObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1499 if( pCurrentObject == NULL &&
1500 pVolumeCB != AFSGlobalRoot)
1503 pCurrentObject = &pVolumeCB->ObjectInformation;
1509 pCurrentObject = NULL;
1514 else if( pCurrentObject->FileType == AFS_FILE_TYPE_FILE)
1517 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1518 pCurrentObject->ObjectReferenceCount == 0 &&
1519 ( pCurrentObject->Fcb == NULL ||
1520 pCurrentObject->Fcb->OpenReferenceCount == 0))
1523 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1525 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1529 if( pCurrentObject->Fcb != NULL)
1532 AFSCleanupFcb( pCurrentObject->Fcb,
1536 // Acquire and drop the Fcb resource to synchronize
1537 // with a potentially active AFSCleanup() which sets
1538 // the OpenReferenceCount to zero while holding the
1542 AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
1545 AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
1547 AFSRemoveFcb( pCurrentObject->Fcb);
1550 AFSDeleteObjectInfo( pCurrentObject);
1552 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1554 pCurrentObject = pNextObject;
1561 bReleaseVolumeLock = FALSE;
1566 else if( pCurrentObject->Fcb != NULL)
1569 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1571 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1575 AFSCleanupFcb( pCurrentObject->Fcb,
1578 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1580 pCurrentObject = pNextObject;
1587 bReleaseVolumeLock = FALSE;
1594 pCurrentObject = pNextObject;
1597 if( bReleaseVolumeLock)
1600 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1608 AFSReleaseResource( pVolumeCB->VolumeLock);
1610 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1613 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1616 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1618 } // worker thread loop
1620 KeCancelTimer( &Timer);
1622 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1623 AFS_TRACE_LEVEL_VERBOSE,
1624 "AFSPrimaryVolumeWorkerThread Exiting\n");
1626 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1631 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1636 PsTerminateSystemThread( 0);
1642 AFSVolumeWorkerThread( IN PVOID Context)
1645 NTSTATUS ntStatus = STATUS_SUCCESS;
1646 AFSVolumeCB *pVolumeCB = (AFSVolumeCB * )Context;
1647 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&pVolumeCB->VolumeWorkerContext;
1648 AFSDeviceExt *pControlDeviceExt = NULL;
1649 AFSDeviceExt *pRDRDeviceExt = NULL;
1650 BOOLEAN exitThread = FALSE;
1651 LARGE_INTEGER DueTime;
1656 pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1658 pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1661 // Initialize the timer for the worker thread
1664 DueTime.QuadPart = -(5000);
1668 KeInitializeTimerEx( &Timer,
1669 SynchronizationTimer);
1671 KeSetTimerEx( &Timer,
1677 // Indicate that we are initialized and ready
1680 KeSetEvent( &pPoolContext->WorkerThreadReady,
1685 // Indicate we are initialized
1688 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1690 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1693 ntStatus = KeWaitForSingleObject( &Timer,
1699 if( !NT_SUCCESS( ntStatus))
1702 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1703 AFS_TRACE_LEVEL_ERROR,
1704 "AFSVolumeWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
1710 // If we are in shutdown mode and the dirty flag is clear then get out now
1713 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1719 } // worker thread loop
1721 KeCancelTimer( &Timer);
1723 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1728 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1733 PsTerminateSystemThread( 0);
1739 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1742 NTSTATUS ntStatus = STATUS_SUCCESS;
1743 AFSDeviceExt *pDevExt = NULL;
1746 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1748 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1749 AFS_TRACE_LEVEL_VERBOSE,
1750 "AFSInsertWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1751 &pDevExt->Specific.Library.QueueLock,
1752 PsGetCurrentThread());
1754 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1757 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1759 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1760 AFS_TRACE_LEVEL_VERBOSE,
1761 "AFSInsertWorkitem Inserting work item %08lX Count %08lX\n",
1765 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1768 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1773 pDevExt->Specific.Library.QueueHead = WorkItem;
1776 WorkItem->next = NULL;
1777 pDevExt->Specific.Library.QueueTail = WorkItem;
1779 // indicate that the queue has nodes
1780 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1784 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1790 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1793 NTSTATUS ntStatus = STATUS_SUCCESS;
1794 AFSDeviceExt *pDevExt = NULL;
1797 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1799 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1800 AFS_TRACE_LEVEL_VERBOSE,
1801 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1802 &pDevExt->Specific.Library.IOQueueLock,
1803 PsGetCurrentThread());
1805 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1808 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
1810 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1811 AFS_TRACE_LEVEL_VERBOSE,
1812 "AFSInsertWorkitem Inserting IO work item %08lX Count %08lX\n",
1816 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
1819 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
1824 pDevExt->Specific.Library.IOQueueHead = WorkItem;
1827 WorkItem->next = NULL;
1828 pDevExt->Specific.Library.IOQueueTail = WorkItem;
1830 // indicate that the queue has nodes
1831 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1835 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
1841 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1844 NTSTATUS ntStatus = STATUS_SUCCESS;
1845 AFSDeviceExt *pDevExt = NULL;
1848 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1850 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1851 AFS_TRACE_LEVEL_VERBOSE,
1852 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1853 &pDevExt->Specific.Library.QueueLock,
1854 PsGetCurrentThread());
1856 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1859 WorkItem->next = pDevExt->Specific.Library.QueueHead;
1861 pDevExt->Specific.Library.QueueHead = WorkItem;
1863 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1865 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1866 AFS_TRACE_LEVEL_VERBOSE,
1867 "AFSInsertWorkitemAtHead Inserting work item %08lX Count %08lX\n",
1872 // indicate that the queue has nodes
1875 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1879 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1888 NTSTATUS ntStatus = STATUS_SUCCESS;
1889 AFSWorkItem *pWorkItem = NULL;
1890 AFSDeviceExt *pDevExt = NULL;
1893 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1895 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1896 AFS_TRACE_LEVEL_VERBOSE,
1897 "AFSRemoveWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1898 &pDevExt->Specific.Library.QueueLock,
1899 PsGetCurrentThread());
1901 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1904 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
1907 pWorkItem = pDevExt->Specific.Library.QueueHead;
1909 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
1911 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1912 AFS_TRACE_LEVEL_VERBOSE,
1913 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1916 PsGetCurrentThreadId());
1918 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
1920 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
1923 pDevExt->Specific.Library.QueueTail = NULL;
1929 // Wake up another worker
1932 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
1938 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
1944 AFSRemoveIOWorkItem()
1947 NTSTATUS ntStatus = STATUS_SUCCESS;
1948 AFSWorkItem *pWorkItem = NULL;
1949 AFSDeviceExt *pDevExt = NULL;
1952 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1954 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1955 AFS_TRACE_LEVEL_VERBOSE,
1956 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %08lX EXCL %08lX\n",
1957 &pDevExt->Specific.Library.IOQueueLock,
1958 PsGetCurrentThread());
1960 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
1963 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
1966 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
1968 lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
1970 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1971 AFS_TRACE_LEVEL_VERBOSE,
1972 "AFSRemoveWorkItem Removing work item %08lX Count %08lX Thread %08lX\n",
1975 PsGetCurrentThreadId());
1977 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
1979 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
1982 pDevExt->Specific.Library.IOQueueTail = NULL;
1988 // Wake up another worker
1991 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
1997 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
2003 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2006 NTSTATUS ntStatus = STATUS_SUCCESS;
2007 AFSDeviceExt *pDevExt = NULL;
2008 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2011 // Submit the work item to the worker
2014 ntStatus = AFSInsertWorkitem( WorkItem);
2020 // Sync request so block on the work item event
2023 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2034 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2037 NTSTATUS ntStatus = STATUS_SUCCESS;
2038 AFSDeviceExt *pDevExt = NULL;
2039 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2042 // Submit the work item to the worker
2045 ntStatus = AFSInsertIOWorkitem( WorkItem);
2051 // Sync request so block on the work item event
2054 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2065 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2068 NTSTATUS ntStatus = STATUS_SUCCESS;
2069 AFSDeviceExt *pDevExt = NULL;
2070 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2073 // Submit the work item to the worker
2076 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2082 // Sync request so block on the work item event
2085 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2096 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2100 NTSTATUS ntStatus = STATUS_SUCCESS;
2101 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2102 AFSWorkItem *pWorkItem = NULL;
2108 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2109 AFS_TRACE_LEVEL_VERBOSE,
2110 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2111 Fcb->ObjectInformation->FileId.Cell,
2112 Fcb->ObjectInformation->FileId.Volume,
2113 Fcb->ObjectInformation->FileId.Vnode,
2114 Fcb->ObjectInformation->FileId.Unique);
2117 // Increment our flush count here just to keep the number of items in the
2118 // queue down. We'll decrement it just below.
2121 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2126 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2127 AFS_TRACE_LEVEL_VERBOSE,
2128 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2129 Fcb->ObjectInformation->FileId.Cell,
2130 Fcb->ObjectInformation->FileId.Volume,
2131 Fcb->ObjectInformation->FileId.Vnode,
2132 Fcb->ObjectInformation->FileId.Unique);
2134 try_return( ntStatus);
2137 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2140 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2141 AFS_TRACE_LEVEL_ERROR,
2142 "AFSQueueFlushExtents Failing request, in shutdown\n");
2144 try_return( ntStatus = STATUS_TOO_LATE);
2148 // Allocate our request structure and send it to the worker
2151 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2152 sizeof( AFSWorkItem),
2155 if( pWorkItem == NULL)
2158 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2159 AFS_TRACE_LEVEL_ERROR,
2160 "AFSQueueFlushExtents Failed to allocate work item\n");
2162 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2165 RtlZeroMemory( pWorkItem,
2166 sizeof( AFSWorkItem));
2168 pWorkItem->Size = sizeof( AFSWorkItem);
2170 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2172 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2174 RtlCopyMemory( &pWorkItem->AuthGroup,
2178 pWorkItem->Specific.Fcb.Fcb = Fcb;
2180 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2182 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2183 AFS_TRACE_LEVEL_VERBOSE,
2184 "AFSQueueFlushExtents Increment count on Fcb %08lX Cnt %d\n",
2188 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2189 AFS_TRACE_LEVEL_VERBOSE,
2190 "AFSQueueFlushExtents Workitem %08lX for FID %08lX-%08lX-%08lX-%08lX\n",
2192 Fcb->ObjectInformation->FileId.Cell,
2193 Fcb->ObjectInformation->FileId.Volume,
2194 Fcb->ObjectInformation->FileId.Vnode,
2195 Fcb->ObjectInformation->FileId.Unique);
2197 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2201 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2202 AFS_TRACE_LEVEL_VERBOSE,
2203 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2204 Fcb->ObjectInformation->FileId.Cell,
2205 Fcb->ObjectInformation->FileId.Volume,
2206 Fcb->ObjectInformation->FileId.Vnode,
2207 Fcb->ObjectInformation->FileId.Unique,
2211 // Remove the count we added above
2214 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2219 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2224 if( !NT_SUCCESS( ntStatus))
2227 if( pWorkItem != NULL)
2230 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2232 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2235 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2236 AFS_TRACE_LEVEL_ERROR,
2237 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2240 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2245 "EXCEPTION - AFSQueueFlushExtents\n");
2252 AFSQueueAsyncRead( IN PDEVICE_OBJECT DeviceObject,
2254 IN HANDLE CallerProcess)
2257 NTSTATUS ntStatus = STATUS_SUCCESS;
2258 AFSWorkItem *pWorkItem = NULL;
2263 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2264 AFS_TRACE_LEVEL_VERBOSE,
2265 "AFSQueueAsyncRead Queuing request for Irp %08lX\n",
2268 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2269 sizeof(AFSWorkItem),
2271 if (NULL == pWorkItem)
2274 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2275 AFS_TRACE_LEVEL_ERROR,
2276 "AFSQueueAsyncRead Failed to allocate work item\n");
2278 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2281 RtlZeroMemory( pWorkItem,
2282 sizeof(AFSWorkItem));
2284 pWorkItem->Size = sizeof( AFSWorkItem);
2286 pWorkItem->RequestType = AFS_WORK_ASYNCH_READ;
2288 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2290 pWorkItem->Specific.AsynchIo.Irp = Irp;
2292 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2294 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2295 AFS_TRACE_LEVEL_VERBOSE,
2296 "AFSQueueAsyncRead Workitem %08lX for Irp %08lX\n",
2300 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2304 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2305 AFS_TRACE_LEVEL_VERBOSE,
2306 "AFSQueueAsyncRead Request for Irp %08lX complete Status %08lX\n",
2310 if( !NT_SUCCESS( ntStatus))
2313 if( pWorkItem != NULL)
2316 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2319 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2320 AFS_TRACE_LEVEL_ERROR,
2321 "AFSQueueAsyncRead Failed to queue request Status %08lX\n", ntStatus);
2324 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2329 "EXCEPTION - AFSQueueAsyncRead\n");
2336 AFSQueueAsyncWrite( IN PDEVICE_OBJECT DeviceObject,
2338 IN HANDLE CallerProcess)
2341 NTSTATUS ntStatus = STATUS_SUCCESS;
2342 AFSWorkItem *pWorkItem = NULL;
2347 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2348 AFS_TRACE_LEVEL_VERBOSE,
2349 "AFSQueueAsyncWrite Queuing request for Irp %08lX\n",
2352 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2353 sizeof(AFSWorkItem),
2355 if (NULL == pWorkItem)
2358 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2359 AFS_TRACE_LEVEL_ERROR,
2360 "AFSQueueAsyncWrite Failed to allocate work item\n");
2362 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2365 RtlZeroMemory( pWorkItem,
2366 sizeof(AFSWorkItem));
2368 pWorkItem->Size = sizeof( AFSWorkItem);
2370 pWorkItem->RequestType = AFS_WORK_ASYNCH_WRITE;
2372 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2374 pWorkItem->Specific.AsynchIo.Irp = Irp;
2376 pWorkItem->Specific.AsynchIo.CallingProcess = CallerProcess;
2378 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2379 AFS_TRACE_LEVEL_VERBOSE,
2380 "AFSQueueAsyncWrite Workitem %08lX for Irp %08lX\n",
2384 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2388 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2389 AFS_TRACE_LEVEL_VERBOSE,
2390 "AFSQueueAsyncWrite Request for Irp %08lX complete Status %08lX\n",
2394 if( !NT_SUCCESS( ntStatus))
2397 if( pWorkItem != NULL)
2400 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2403 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2404 AFS_TRACE_LEVEL_ERROR,
2405 "AFSQueueAsyncWrite Failed to queue request Status %08lX\n", ntStatus);
2408 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2413 "EXCEPTION - AFSQueueAsyncWrite\n");
2420 AFSQueueGlobalRootEnumeration()
2423 NTSTATUS ntStatus = STATUS_SUCCESS;
2424 AFSWorkItem *pWorkItem = NULL;
2429 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2430 sizeof(AFSWorkItem),
2432 if (NULL == pWorkItem)
2435 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2436 AFS_TRACE_LEVEL_ERROR,
2437 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2439 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2442 RtlZeroMemory( pWorkItem,
2443 sizeof(AFSWorkItem));
2445 pWorkItem->Size = sizeof( AFSWorkItem);
2447 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2449 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2450 AFS_TRACE_LEVEL_VERBOSE,
2451 "AFSQueueGlobalRootEnumeration Workitem %08lX\n",
2454 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2458 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2459 AFS_TRACE_LEVEL_VERBOSE,
2460 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2463 if( !NT_SUCCESS( ntStatus))
2466 if( pWorkItem != NULL)
2469 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2472 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2473 AFS_TRACE_LEVEL_ERROR,
2474 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2478 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2483 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2490 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2491 IN UCHAR FunctionCode,
2492 IN ULONG RequestFlags,
2493 IN AFSIoRun *IoRuns,
2495 IN AFSGatherIo *GatherIo)
2498 NTSTATUS ntStatus = STATUS_SUCCESS;
2499 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2500 AFSWorkItem *pWorkItem = NULL;
2505 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2508 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2509 AFS_TRACE_LEVEL_ERROR,
2510 "AFSQueueStartIos Failing request, in shutdown\n");
2512 try_return( ntStatus = STATUS_TOO_LATE);
2516 // Allocate our request structure and send it to the worker
2519 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2520 sizeof( AFSWorkItem),
2523 if( pWorkItem == NULL)
2526 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2527 AFS_TRACE_LEVEL_ERROR,
2528 "AFSQueueStartIos Failed to allocate work item\n");
2530 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2533 RtlZeroMemory( pWorkItem,
2534 sizeof( AFSWorkItem));
2536 KeInitializeEvent( &pWorkItem->Event,
2540 pWorkItem->Size = sizeof( AFSWorkItem);
2542 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2544 pWorkItem->RequestType = AFS_WORK_START_IOS;
2546 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2548 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2550 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2552 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2554 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2556 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2558 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2559 AFS_TRACE_LEVEL_VERBOSE,
2560 "AFSQueueStartIos Queuing IO Workitem %08lX\n",
2563 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2567 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2568 AFS_TRACE_LEVEL_VERBOSE,
2569 "AFSQueueStartIos Request complete Status %08lX\n",
2572 if( !NT_SUCCESS( ntStatus))
2575 if( pWorkItem != NULL)
2578 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2582 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2587 "EXCEPTION - AFSQueueStartIos\n");
2594 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2595 IN ULONG InvalidateReason)
2598 NTSTATUS ntStatus = STATUS_SUCCESS;
2599 AFSWorkItem *pWorkItem = NULL;
2604 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2605 sizeof(AFSWorkItem),
2607 if (NULL == pWorkItem)
2610 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2611 AFS_TRACE_LEVEL_ERROR,
2612 "AFSQueueInvalidateObject Failed to allocate work item\n");
2614 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2617 RtlZeroMemory( pWorkItem,
2618 sizeof(AFSWorkItem));
2620 pWorkItem->Size = sizeof( AFSWorkItem);
2622 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2624 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2626 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2628 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2629 AFS_TRACE_LEVEL_VERBOSE,
2630 "AFSQueueInvalidateObject Workitem %08lX\n",
2633 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2637 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2638 AFS_TRACE_LEVEL_VERBOSE,
2639 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2642 if( !NT_SUCCESS( ntStatus))
2645 if( pWorkItem != NULL)
2647 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2650 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2651 AFS_TRACE_LEVEL_ERROR,
2652 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2656 __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
2661 "EXCEPTION - AFSQueueInvalidateObject\n");