2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSWorker.cpp
39 #include "AFSCommon.h"
42 // Function: AFSInitializeWorkerPool
46 // This function initializes the worker thread pool
50 // A status is returned for the function
54 AFSInitializeWorkerPool()
57 NTSTATUS ntStatus = STATUS_SUCCESS;
58 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
59 AFSDeviceExt *pDevExt = NULL;
64 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
67 // Initialize the worker threads.
70 pDevExt->Specific.Library.WorkerCount = 0;
72 KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
77 // Initialize the queue resource
80 ExInitializeResourceLite( &pDevExt->Specific.Library.QueueLock);
82 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
85 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
86 sizeof( AFSWorkQueueContext),
89 if( pCurrentWorker == NULL)
92 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
93 AFS_TRACE_LEVEL_ERROR,
94 "AFSInitializeWorkerPool Failed to allocate worker context\n");
96 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
101 RtlZeroMemory( pCurrentWorker,
102 sizeof( AFSWorkQueueContext));
104 ntStatus = AFSInitWorkerThread( pCurrentWorker,
105 (PKSTART_ROUTINE)AFSWorkerThread);
107 if( !NT_SUCCESS( ntStatus))
110 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
111 AFS_TRACE_LEVEL_ERROR,
112 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
114 ExFreePool( pCurrentWorker);
119 if( pDevExt->Specific.Library.PoolHead == NULL)
122 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
127 pLastWorker->fLink = pCurrentWorker;
130 pLastWorker = pCurrentWorker;
132 pDevExt->Specific.Library.WorkerCount++;
136 // If there was a failure but there is at least one worker, then go with it.
139 if( !NT_SUCCESS( ntStatus) &&
140 pDevExt->Specific.Library.WorkerCount == 0)
143 try_return( ntStatus);
146 ntStatus = STATUS_SUCCESS;
149 // Now our IO Worker queue
152 pDevExt->Specific.Library.IOWorkerCount = 0;
154 KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
155 SynchronizationEvent,
159 // Initialize the queue resource
162 ExInitializeResourceLite( &pDevExt->Specific.Library.IOQueueLock);
164 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
167 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
168 sizeof( AFSWorkQueueContext),
171 if( pCurrentWorker == NULL)
174 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
178 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
183 RtlZeroMemory( pCurrentWorker,
184 sizeof( AFSWorkQueueContext));
186 ntStatus = AFSInitWorkerThread( pCurrentWorker,
187 (PKSTART_ROUTINE)AFSIOWorkerThread);
189 if( !NT_SUCCESS( ntStatus))
192 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
193 AFS_TRACE_LEVEL_ERROR,
194 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
196 ExFreePool( pCurrentWorker);
201 if( pDevExt->Specific.Library.IOPoolHead == NULL)
204 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
209 pLastWorker->fLink = pCurrentWorker;
212 pLastWorker = pCurrentWorker;
214 pDevExt->Specific.Library.IOWorkerCount++;
218 // If there was a failure but there is at least one worker, then go with it.
221 if( !NT_SUCCESS( ntStatus) &&
222 pDevExt->Specific.Library.IOWorkerCount == 0)
225 try_return( ntStatus);
230 if( !NT_SUCCESS( ntStatus))
234 // Failed to initialize the pool so tear it down
237 AFSRemoveWorkerPool();
245 // Function: AFSRemoveWorkerPool
249 // This function tears down the worker thread pool
253 // A status is returned for the function
257 AFSRemoveWorkerPool()
260 NTSTATUS ntStatus = STATUS_SUCCESS;
262 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
263 AFSDeviceExt *pDevExt = NULL;
265 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
268 // Loop through the workers shutting them down in two stages.
269 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
270 // stop processing requests. Second, call AFSShutdownWorkerThread()
271 // to wake the workers and wait for them to exit.
274 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
276 while( index < pDevExt->Specific.Library.WorkerCount)
279 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
281 pCurrentWorker = pCurrentWorker->fLink;
283 if ( pCurrentWorker == NULL)
292 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
296 while( index < pDevExt->Specific.Library.WorkerCount)
299 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
301 pNextWorker = pCurrentWorker->fLink;
303 ExFreePool( pCurrentWorker);
305 pCurrentWorker = pNextWorker;
307 if( pCurrentWorker == NULL)
316 pDevExt->Specific.Library.PoolHead = NULL;
318 ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
321 // Loop through the IO workers shutting them down in two stages.
322 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
323 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
324 // to wake the workers and wait for them to exit.
327 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
331 while( index < pDevExt->Specific.Library.IOWorkerCount)
334 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
336 pCurrentWorker = pCurrentWorker->fLink;
338 if ( pCurrentWorker == NULL)
347 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
351 while( index < pDevExt->Specific.Library.IOWorkerCount)
354 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
356 pNextWorker = pCurrentWorker->fLink;
358 ExFreePool( pCurrentWorker);
360 pCurrentWorker = pNextWorker;
362 if( pCurrentWorker == NULL)
371 pDevExt->Specific.Library.IOPoolHead = NULL;
373 ExDeleteResourceLite( &pDevExt->Specific.Library.IOQueueLock);
379 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
382 NTSTATUS ntStatus = STATUS_SUCCESS;
383 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
385 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
386 PKSTART_ROUTINE pStartRoutine = NULL;
392 if ( VolumeCB != AFSGlobalRoot)
395 return STATUS_INVALID_PARAMETER;
398 pStartRoutine = AFSPrimaryVolumeWorkerThread;
401 // Initialize the worker thread
404 KeInitializeEvent( &pWorker->WorkerThreadReady,
409 // Set the worker to process requests
412 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
418 ntStatus = PsCreateSystemThread( &hThread,
426 if( NT_SUCCESS( ntStatus))
429 ObReferenceObjectByHandle( hThread,
430 GENERIC_READ | GENERIC_WRITE,
433 (PVOID *)&pWorker->WorkerThreadObject,
436 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
442 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
447 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
458 // Function: AFSInitWorkerThread
462 // This function initializes a worker thread in the pool
466 // A status is returned for the function
470 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
471 IN PKSTART_ROUTINE WorkerRoutine)
474 NTSTATUS ntStatus = STATUS_SUCCESS;
478 // INitialize the worker signal thread
481 KeInitializeEvent( &PoolContext->WorkerThreadReady,
486 // Set the worker to process requests
489 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
495 ntStatus = PsCreateSystemThread( &Handle,
501 (void *)PoolContext);
503 if( NT_SUCCESS( ntStatus))
506 ObReferenceObjectByHandle( Handle,
507 GENERIC_READ | GENERIC_WRITE,
510 (PVOID *)&PoolContext->WorkerThreadObject,
513 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
526 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
529 NTSTATUS ntStatus = STATUS_SUCCESS;
530 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
533 // Clear the 'keep processing' flag
536 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
538 if( pWorker->WorkerThreadObject != NULL)
540 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
543 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
550 ObDereferenceObject( pWorker->WorkerThreadObject);
552 pWorker->WorkerThreadObject = NULL;
559 // Function: AFSShutdownWorkerThread
563 // This function shutsdown a worker thread in the pool
567 // A status is returned for the function
571 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
574 NTSTATUS ntStatus = STATUS_SUCCESS;
575 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
577 if( PoolContext->WorkerThreadObject != NULL)
580 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
584 // Wake up the thread if it is a sleep
587 KeSetEvent( &pDeviceExt->Specific.Library.WorkerQueueHasItems,
591 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
598 ObDereferenceObject( PoolContext->WorkerThreadObject);
600 PoolContext->WorkerThreadObject = NULL;
607 // Function: AFSShutdownIOWorkerThread
611 // This function shutsdown an IO worker thread in the pool
615 // A status is returned for the function
619 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
622 NTSTATUS ntStatus = STATUS_SUCCESS;
623 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
625 if( PoolContext->WorkerThreadObject != NULL)
628 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
632 // Wake up the thread if it is a sleep
635 KeSetEvent( &pDeviceExt->Specific.Library.IOWorkerQueueHasItems,
639 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
646 ObDereferenceObject( PoolContext->WorkerThreadObject);
648 PoolContext->WorkerThreadObject = NULL;
655 // Function: AFSWorkerThread
659 // This is the worker thread entry point.
663 // A status is returned for the function
667 AFSWorkerThread( IN PVOID Context)
670 NTSTATUS ntStatus = STATUS_SUCCESS;
671 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
672 AFSWorkItem *pWorkItem;
673 BOOLEAN freeWorkItem = TRUE;
674 AFSDeviceExt *pLibraryDevExt = NULL;
677 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
680 // Indicate that we are initialized and ready
683 KeSetEvent( &pPoolContext->WorkerThreadReady,
688 // Indicate we are initialized
691 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
693 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
699 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
702 if( !NT_SUCCESS( ntStatus))
705 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
706 AFS_TRACE_LEVEL_ERROR,
707 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
709 ntStatus = STATUS_SUCCESS;
714 pWorkItem = AFSRemoveWorkItem();
716 if( pWorkItem == NULL)
719 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
731 // Switch on the type of work item to process
734 switch( pWorkItem->RequestType)
737 case AFS_WORK_FLUSH_FCB:
740 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
741 &pWorkItem->AuthGroup);
743 if( !NT_SUCCESS( ntStatus))
746 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
747 &pWorkItem->AuthGroup,
751 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
753 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
758 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
761 AFSEnumerateGlobalRoot( NULL);
766 case AFS_WORK_INVALIDATE_OBJECT:
769 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
770 pWorkItem->Specific.Invalidate.InvalidateReason);
777 case AFS_WORK_START_IOS:
787 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
788 AFS_TRACE_LEVEL_ERROR,
789 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
797 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
800 ntStatus = STATUS_SUCCESS;
803 } // worker thread loop
805 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
807 // Wake up another worker so they too can exit
809 KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
813 PsTerminateSystemThread( 0);
819 AFSIOWorkerThread( IN PVOID Context)
822 NTSTATUS ntStatus = STATUS_SUCCESS;
823 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
824 AFSWorkItem *pWorkItem;
825 BOOLEAN freeWorkItem = TRUE;
826 AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
828 pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
831 // Indicate that we are initialized and ready
834 KeSetEvent( &pPoolContext->WorkerThreadReady,
840 // Indicate we are initialized
843 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
845 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
851 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
854 if( !NT_SUCCESS( ntStatus))
857 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
858 AFS_TRACE_LEVEL_ERROR,
859 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
861 ntStatus = STATUS_SUCCESS;
866 pWorkItem = AFSRemoveIOWorkItem();
868 if( pWorkItem == NULL)
871 ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
883 // Switch on the type of work item to process
886 switch( pWorkItem->RequestType)
889 case AFS_WORK_START_IOS:
892 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
895 // The final status is in the gather io
898 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
899 pWorkItem->Specific.CacheAccess.FunctionCode,
900 pWorkItem->Specific.CacheAccess.RequestFlags,
901 pWorkItem->Specific.CacheAccess.IoRuns,
902 pWorkItem->Specific.CacheAccess.RunCount,
903 pWorkItem->Specific.CacheAccess.GatherIo);
906 // Regardless of the status we we do the complete - there may
908 // Decrement the count - setting the event if we were told
909 // to. This may trigger completion.
912 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
921 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
922 AFS_TRACE_LEVEL_ERROR,
923 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
931 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
934 ntStatus = STATUS_SUCCESS;
937 } // worker thread loop
939 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
941 // Wake up another IOWorker so they too can exit
943 KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
947 PsTerminateSystemThread( 0);
953 AFSExamineDirectory( IN AFSObjectInfoCB * pCurrentObject,
954 IN AFSDirectoryCB * pCurrentDirEntry)
958 AFSObjectInfoCB *pCurrentChildObject = NULL;
959 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
960 BOOLEAN bFcbBusy = FALSE;
963 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
965 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
966 AFS_TRACE_LEVEL_VERBOSE,
967 "AFSExamineDirectory Deleting DE %wZ Object %p\n",
968 &pCurrentDirEntry->NameInformation.FileName,
969 pCurrentChildObject);
971 AFSDeleteDirEntry( pCurrentObject,
975 // Acquire ObjectInfoLock shared here so as not to deadlock
976 // with an invalidation call from the service during AFSCleanupFcb
979 lCount = AFSObjectInfoIncrement( pCurrentChildObject,
980 AFS_OBJECT_REFERENCE_WORKER);
982 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
983 AFS_TRACE_LEVEL_VERBOSE,
984 "AFSExamineDirectory Increment count on object %p Cnt %d\n",
989 pCurrentChildObject->Fcb != NULL &&
990 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
994 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
995 // across an AFSCleanupFcb call since it can deadlock with an
996 // invalidation call from the service.
999 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1002 // Cannot hold a TreeLock across an AFSCleanupFcb call
1003 // as it can deadlock with an invalidation ioctl initiated
1004 // from the service.
1006 // Dropping the TreeLock permits the
1007 // pCurrentObject->ObjectReferenceCount to change
1010 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1013 if ( ntStatus == STATUS_RETRY)
1019 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1023 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1026 lCount = AFSObjectInfoDecrement( pCurrentChildObject,
1027 AFS_OBJECT_REFERENCE_WORKER);
1029 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1030 AFS_TRACE_LEVEL_VERBOSE,
1031 "AFSExamineDirectory Decrement1 count on object %p Cnt %d\n",
1032 pCurrentChildObject,
1036 pCurrentChildObject->Fcb != NULL &&
1037 pCurrentChildObject->Fcb->OpenReferenceCount == 0)
1040 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1042 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1043 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1046 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1049 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1051 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1053 AFSDeleteObjectInfo( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1055 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1057 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1059 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSExamineDirectory (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1062 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1064 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1067 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1069 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1070 AFS_TRACE_LEVEL_VERBOSE,
1071 "AFSExamineDirectory Deleting object %p\n",
1072 pCurrentChildObject);
1074 AFSDeleteObjectInfo( &pCurrentChildObject);
1079 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1086 // Called with VolumeCB->ObjectInfoTree.TreeLock held shared.
1087 // The TreeLock will be released unless *pbReleaseVolumeLock is set to FALSE.
1091 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
1092 IN BOOLEAN bVolumeObject,
1093 IN OUT BOOLEAN * pbReleaseVolumeLock)
1095 NTSTATUS ntStatus = STATUS_SUCCESS;
1096 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1097 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1098 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
1099 AFSObjectInfoCB *pCurrentChildObject = NULL;
1100 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
1101 LARGE_INTEGER liCurrentTime;
1102 BOOLEAN bFcbBusy = FALSE;
1106 switch ( pCurrentObject->FileType) {
1108 case AFS_FILE_TYPE_DIRECTORY:
1111 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1118 // If this object is deleted then remove it from the parent, if we can
1121 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1122 pCurrentObject->ObjectReferenceCount <= 0 &&
1123 ( pCurrentObject->Fcb == NULL ||
1124 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1125 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1126 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1129 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1132 // Dropping the TreeLock permits the
1133 // pCurrentObject->ObjectReferenceCount to change
1136 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1140 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1143 if ( pCurrentObject->ObjectReferenceCount <= 0)
1146 AFSRemoveFcb( &pCurrentObject->Fcb);
1148 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1151 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1154 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1156 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1158 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1160 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1162 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1164 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1165 AFS_TRACE_LEVEL_VERBOSE,
1166 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1167 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1169 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1172 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1174 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1175 AFS_TRACE_LEVEL_VERBOSE,
1176 "AFSExamineObjectInfo Deleting deleted object %p\n",
1179 AFSDeleteObjectInfo( &pCurrentObject);
1184 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1187 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1192 *pbReleaseVolumeLock = FALSE;
1198 if ( pCurrentObject->Fcb != NULL &&
1199 pCurrentObject->Fcb->CcbListHead != NULL)
1204 for ( pCcb = pCurrentObject->Fcb->CcbListHead;
1206 pCcb = (AFSCcb *)pCcb->ListEntry.fLink)
1209 if ( pCcb->NameArray) {
1211 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1212 AFS_TRACE_LEVEL_VERBOSE,
1213 "AFSExamineObjectInfo Found Object %p Fcb %p Ccb %p\n",
1215 pCurrentObject->Fcb,
1223 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1224 ( pCurrentObject->Fcb != NULL &&
1225 pCurrentObject->Fcb->OpenReferenceCount > 0))
1231 if ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
1232 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1235 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1242 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1245 // Directory Entry Processing
1248 KeQueryTickCount( &liCurrentTime);
1250 while( pCurrentDirEntry != NULL)
1253 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1259 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1265 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1266 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1272 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1273 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1274 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1280 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1283 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1289 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1296 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1299 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1300 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1307 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1310 if( pCurrentDirEntry != NULL)
1313 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1318 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1320 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1323 // Now acquire the locks excl without deadlocking
1326 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1330 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1334 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1336 *pbReleaseVolumeLock = FALSE;
1341 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1344 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1346 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1351 KeQueryTickCount( &liCurrentTime);
1353 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1355 while( pCurrentDirEntry != NULL)
1358 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1364 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1370 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1371 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1377 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1378 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1379 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1385 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1388 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1394 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1401 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1404 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1405 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1412 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1415 if( pCurrentDirEntry != NULL)
1418 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1420 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1425 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1427 while( pCurrentDirEntry != NULL)
1430 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1432 AFSExamineDirectory( pCurrentObject,
1435 pCurrentDirEntry = pNextDirEntry;
1439 // Clear our enumerated flag on this object so we retrieve info again on next access
1442 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1444 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1446 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1452 // Try to grab the volume lock again ... no problem if we don't
1455 if( !AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1459 *pbReleaseVolumeLock = FALSE;
1465 else if ( bVolumeObject == FALSE)
1471 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1473 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1477 *pbReleaseVolumeLock = FALSE;
1482 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1485 KeQueryTickCount( &liCurrentTime);
1487 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1488 ( pCurrentObject->Fcb == NULL ||
1489 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1490 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1491 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1492 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1495 AFSRemoveFcb( &pCurrentObject->Fcb);
1497 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1499 AFSDeleteObjectInfo( &pCurrentObject);
1504 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1507 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1512 case AFS_FILE_TYPE_FILE:
1515 lCount = AFSObjectInfoIncrement( pCurrentObject,
1516 AFS_OBJECT_REFERENCE_WORKER);
1518 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1519 AFS_TRACE_LEVEL_VERBOSE,
1520 "AFSExamineObjectInfo Increment3 count on object %p Cnt %d\n",
1524 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1526 if( pCurrentObject->Fcb != NULL)
1530 // Dropping the TreeLock permits the
1531 // pCurrentObject->ObjectReferenceCount to change
1534 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1537 if ( ntStatus == STATUS_RETRY)
1544 bTemp = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1547 lCount = AFSObjectInfoDecrement( pCurrentObject,
1548 AFS_OBJECT_REFERENCE_WORKER);
1550 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1551 AFS_TRACE_LEVEL_VERBOSE,
1552 "AFSExamineObjectInfo Decrement3 count on object %p Cnt %d\n",
1557 if ( bTemp == FALSE)
1560 *pbReleaseVolumeLock = FALSE;
1565 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1568 KeQueryTickCount( &liCurrentTime);
1570 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1571 ( pCurrentObject->Fcb == NULL ||
1572 ( pCurrentObject->Fcb->OpenReferenceCount <= 0 &&
1573 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount <= 0)) &&
1574 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1575 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1576 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1579 AFSRemoveFcb( &pCurrentObject->Fcb);
1581 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1583 AFSDeleteObjectInfo( &pCurrentObject);
1588 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1591 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1598 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1600 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1604 *pbReleaseVolumeLock = FALSE;
1609 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1612 KeQueryTickCount( &liCurrentTime);
1614 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1615 ( pCurrentObject->Fcb == NULL ||
1616 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1617 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1618 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1619 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1622 AFSRemoveFcb( &pCurrentObject->Fcb);
1624 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1626 AFSDeleteObjectInfo( &pCurrentObject);
1631 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1634 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1643 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1645 NTSTATUS ntStatus = STATUS_SUCCESS;
1646 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1647 BOOLEAN bReleaseVolumeLock = FALSE;
1648 BOOLEAN bVolumeObject = FALSE;
1649 BOOLEAN bFcbBusy = FALSE;
1652 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1656 bReleaseVolumeLock = TRUE;
1658 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1662 while( pCurrentObject != NULL)
1665 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1668 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1671 // If the end of the VolumeCB ObjectInfo List is reached, then
1672 // the next ObjectInformationCB to examine is the one embedded within
1673 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1675 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1676 // is being examined.
1679 if( pNextObject == NULL &&
1680 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1683 pNextObject = &pVolumeCB->ObjectInformation;
1686 bVolumeObject = FALSE;
1691 lCount = AFSObjectInfoIncrement( pNextObject,
1692 AFS_OBJECT_REFERENCE_WORKER);
1694 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1695 AFS_TRACE_LEVEL_VERBOSE,
1696 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1706 bVolumeObject = TRUE;
1709 bFcbBusy = AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeLock);
1714 lCount = AFSObjectInfoDecrement( pNextObject,
1715 AFS_OBJECT_REFERENCE_WORKER);
1717 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1718 AFS_TRACE_LEVEL_VERBOSE,
1719 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1725 // If AFSExamineObjectInfo drops the VolumeLock before returning
1726 // we must halt processing of the Volume's ObjectInfo list.
1729 if ( bReleaseVolumeLock == FALSE)
1735 pCurrentObject = pNextObject;
1738 if( bReleaseVolumeLock)
1741 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1749 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1752 UNREFERENCED_PARAMETER(Context);
1753 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1754 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1755 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1756 LARGE_INTEGER DueTime;
1759 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1760 BOOLEAN bFcbBusy = FALSE;
1763 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1764 AFS_TRACE_LEVEL_VERBOSE,
1765 "AFSPrimaryVolumeWorkerThread Initialized\n");
1768 // Initialize the timer for the worker thread
1771 DueTime.QuadPart = -(5000);
1775 KeInitializeTimerEx( &Timer,
1776 SynchronizationTimer);
1778 KeSetTimerEx( &Timer,
1784 // Indicate that we are initialized and ready
1787 KeSetEvent( &pPoolContext->WorkerThreadReady,
1792 // Indicate we are initialized
1795 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1797 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1800 if ( bFcbBusy == FALSE)
1803 KeWaitForSingleObject( &Timer,
1816 // This is the primary volume worker so it will traverse the volume list
1817 // looking for cleanup or volumes requiring private workers
1820 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1823 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1825 while( pVolumeCB != NULL)
1828 if( pVolumeCB == AFSGlobalRoot ||
1829 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1833 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1838 if( pVolumeCB->ObjectInfoListHead == NULL)
1841 AFSReleaseResource( pVolumeCB->VolumeLock);
1843 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1845 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1848 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1851 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1855 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1857 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1859 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1864 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1866 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1870 // If VolumeCB is idle, the Volume can be garbage collected
1873 if( pVolumeCB->ObjectInfoListHead == NULL &&
1874 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1875 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1876 pVolumeCB->VolumeReferenceCount == 0 &&
1877 ( pVolumeCB->RootFcb == NULL ||
1878 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1879 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1882 AFSRemoveRootFcb( pVolumeCB);
1884 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1886 AFSRemoveVolume( pVolumeCB);
1891 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1893 AFSReleaseResource( pVolumeCB->VolumeLock);
1896 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1898 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1900 pVolumeCB = pNextVolume;
1906 // Don't need this lock anymore now that we have a volume cb to work with
1909 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1912 // For now we only need the volume lock shared
1915 AFSConvertToShared( pVolumeCB->VolumeLock);
1917 AFSExamineVolume( pVolumeCB);
1923 AFSReleaseResource( pVolumeCB->VolumeLock);
1925 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1928 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1931 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1933 } // worker thread loop
1935 KeCancelTimer( &Timer);
1937 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1939 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1940 AFS_TRACE_LEVEL_VERBOSE,
1941 "AFSPrimaryVolumeWorkerThread Exiting\n");
1943 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1948 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1953 PsTerminateSystemThread( 0);
1959 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1962 NTSTATUS ntStatus = STATUS_SUCCESS;
1963 AFSDeviceExt *pDevExt = NULL;
1966 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
1968 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1969 AFS_TRACE_LEVEL_VERBOSE,
1970 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1971 &pDevExt->Specific.Library.QueueLock,
1972 PsGetCurrentThread());
1974 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
1977 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
1979 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1980 AFS_TRACE_LEVEL_VERBOSE,
1981 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1985 if( pDevExt->Specific.Library.QueueTail != NULL) // queue already has nodes
1988 pDevExt->Specific.Library.QueueTail->next = WorkItem;
1993 pDevExt->Specific.Library.QueueHead = WorkItem;
1996 WorkItem->next = NULL;
1997 pDevExt->Specific.Library.QueueTail = WorkItem;
1999 // indicate that the queue has nodes
2000 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
2004 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
2010 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
2013 NTSTATUS ntStatus = STATUS_SUCCESS;
2014 AFSDeviceExt *pDevExt = NULL;
2017 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
2019 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2020 AFS_TRACE_LEVEL_VERBOSE,
2021 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2022 &pDevExt->Specific.Library.IOQueueLock,
2023 PsGetCurrentThread());
2025 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
2028 lCount = InterlockedIncrement( &pDevExt->Specific.Library.IOQueueItemCount);
2030 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2031 AFS_TRACE_LEVEL_VERBOSE,
2032 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
2036 if( pDevExt->Specific.Library.IOQueueTail != NULL) // queue already has nodes
2039 pDevExt->Specific.Library.IOQueueTail->next = WorkItem;
2044 pDevExt->Specific.Library.IOQueueHead = WorkItem;
2047 WorkItem->next = NULL;
2048 pDevExt->Specific.Library.IOQueueTail = WorkItem;
2050 // indicate that the queue has nodes
2051 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
2055 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
2061 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2064 NTSTATUS ntStatus = STATUS_SUCCESS;
2065 AFSDeviceExt *pDevExt = NULL;
2068 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
2070 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2071 AFS_TRACE_LEVEL_VERBOSE,
2072 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2073 &pDevExt->Specific.Library.QueueLock,
2074 PsGetCurrentThread());
2076 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
2079 WorkItem->next = pDevExt->Specific.Library.QueueHead;
2081 pDevExt->Specific.Library.QueueHead = WorkItem;
2083 lCount = InterlockedIncrement( &pDevExt->Specific.Library.QueueItemCount);
2085 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2086 AFS_TRACE_LEVEL_VERBOSE,
2087 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2092 // indicate that the queue has nodes
2095 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
2099 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
2108 AFSWorkItem *pWorkItem = NULL;
2109 AFSDeviceExt *pDevExt = NULL;
2112 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
2114 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2115 AFS_TRACE_LEVEL_VERBOSE,
2116 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2117 &pDevExt->Specific.Library.QueueLock,
2118 PsGetCurrentThread());
2120 AFSAcquireExcl( &pDevExt->Specific.Library.QueueLock,
2123 if( pDevExt->Specific.Library.QueueHead != NULL) // queue has nodes
2126 pWorkItem = pDevExt->Specific.Library.QueueHead;
2128 lCount = InterlockedDecrement( &pDevExt->Specific.Library.QueueItemCount);
2130 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2131 AFS_TRACE_LEVEL_VERBOSE,
2132 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2135 PsGetCurrentThreadId());
2137 pDevExt->Specific.Library.QueueHead = pDevExt->Specific.Library.QueueHead->next;
2139 if( pDevExt->Specific.Library.QueueHead == NULL) // if queue just became empty
2142 pDevExt->Specific.Library.QueueTail = NULL;
2148 // Wake up another worker
2151 KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
2157 AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
2163 AFSRemoveIOWorkItem()
2166 AFSWorkItem *pWorkItem = NULL;
2167 AFSDeviceExt *pDevExt = NULL;
2170 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
2172 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2173 AFS_TRACE_LEVEL_VERBOSE,
2174 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2175 &pDevExt->Specific.Library.IOQueueLock,
2176 PsGetCurrentThread());
2178 AFSAcquireExcl( &pDevExt->Specific.Library.IOQueueLock,
2181 if( pDevExt->Specific.Library.IOQueueHead != NULL) // queue has nodes
2184 pWorkItem = pDevExt->Specific.Library.IOQueueHead;
2186 lCount = InterlockedDecrement( &pDevExt->Specific.Library.IOQueueItemCount);
2188 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2189 AFS_TRACE_LEVEL_VERBOSE,
2190 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2193 PsGetCurrentThreadId());
2195 pDevExt->Specific.Library.IOQueueHead = pDevExt->Specific.Library.IOQueueHead->next;
2197 if( pDevExt->Specific.Library.IOQueueHead == NULL) // if queue just became empty
2200 pDevExt->Specific.Library.IOQueueTail = NULL;
2206 // Wake up another worker
2209 KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
2215 AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
2221 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2224 NTSTATUS ntStatus = STATUS_SUCCESS;
2225 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2228 // Submit the work item to the worker
2231 ntStatus = AFSInsertWorkitem( WorkItem);
2237 // Sync request so block on the work item event
2240 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2251 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2254 NTSTATUS ntStatus = STATUS_SUCCESS;
2255 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2258 // Submit the work item to the worker
2261 ntStatus = AFSInsertIOWorkitem( WorkItem);
2267 // Sync request so block on the work item event
2270 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2281 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2284 NTSTATUS ntStatus = STATUS_SUCCESS;
2285 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2288 // Submit the work item to the worker
2291 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2297 // Sync request so block on the work item event
2300 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2311 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2315 NTSTATUS ntStatus = STATUS_SUCCESS;
2316 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2317 AFSWorkItem *pWorkItem = NULL;
2323 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2324 AFS_TRACE_LEVEL_VERBOSE,
2325 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2326 Fcb->ObjectInformation->FileId.Cell,
2327 Fcb->ObjectInformation->FileId.Volume,
2328 Fcb->ObjectInformation->FileId.Vnode,
2329 Fcb->ObjectInformation->FileId.Unique);
2332 // Increment our flush count here just to keep the number of items in the
2333 // queue down. We'll decrement it just below.
2336 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2341 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2342 AFS_TRACE_LEVEL_VERBOSE,
2343 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2344 Fcb->ObjectInformation->FileId.Cell,
2345 Fcb->ObjectInformation->FileId.Volume,
2346 Fcb->ObjectInformation->FileId.Vnode,
2347 Fcb->ObjectInformation->FileId.Unique);
2349 try_return( ntStatus);
2352 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2355 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2356 AFS_TRACE_LEVEL_ERROR,
2357 "AFSQueueFlushExtents Failing request, in shutdown\n");
2359 try_return( ntStatus = STATUS_TOO_LATE);
2363 // Allocate our request structure and send it to the worker
2366 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2367 sizeof( AFSWorkItem),
2370 if( pWorkItem == NULL)
2373 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2374 AFS_TRACE_LEVEL_ERROR,
2375 "AFSQueueFlushExtents Failed to allocate work item\n");
2377 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2380 RtlZeroMemory( pWorkItem,
2381 sizeof( AFSWorkItem));
2383 pWorkItem->Size = sizeof( AFSWorkItem);
2385 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2387 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2389 if ( AuthGroup == NULL)
2392 RtlZeroMemory( &pWorkItem->AuthGroup,
2395 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2398 &pWorkItem->AuthGroup);
2402 RtlCopyMemory( &pWorkItem->AuthGroup,
2407 pWorkItem->Specific.Fcb.Fcb = Fcb;
2409 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2411 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2412 AFS_TRACE_LEVEL_VERBOSE,
2413 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2417 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2418 AFS_TRACE_LEVEL_VERBOSE,
2419 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2421 Fcb->ObjectInformation->FileId.Cell,
2422 Fcb->ObjectInformation->FileId.Volume,
2423 Fcb->ObjectInformation->FileId.Vnode,
2424 Fcb->ObjectInformation->FileId.Unique);
2426 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2430 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2431 AFS_TRACE_LEVEL_VERBOSE,
2432 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2433 Fcb->ObjectInformation->FileId.Cell,
2434 Fcb->ObjectInformation->FileId.Volume,
2435 Fcb->ObjectInformation->FileId.Vnode,
2436 Fcb->ObjectInformation->FileId.Unique,
2440 // Remove the count we added above
2443 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2445 ASSERT( lCount >= 0);
2450 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2455 if( !NT_SUCCESS( ntStatus))
2458 if( pWorkItem != NULL)
2461 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2463 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2466 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2467 AFS_TRACE_LEVEL_ERROR,
2468 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2471 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2476 "EXCEPTION - AFSQueueFlushExtents\n");
2478 AFSDumpTraceFilesFnc();
2485 AFSQueueGlobalRootEnumeration()
2488 NTSTATUS ntStatus = STATUS_SUCCESS;
2489 AFSWorkItem *pWorkItem = NULL;
2494 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2495 sizeof(AFSWorkItem),
2497 if (NULL == pWorkItem)
2500 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2501 AFS_TRACE_LEVEL_ERROR,
2502 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2504 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2507 RtlZeroMemory( pWorkItem,
2508 sizeof(AFSWorkItem));
2510 pWorkItem->Size = sizeof( AFSWorkItem);
2512 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2514 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2515 AFS_TRACE_LEVEL_VERBOSE,
2516 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2519 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2523 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2524 AFS_TRACE_LEVEL_VERBOSE,
2525 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2528 if( !NT_SUCCESS( ntStatus))
2531 if( pWorkItem != NULL)
2534 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2537 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2538 AFS_TRACE_LEVEL_ERROR,
2539 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2543 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2548 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2550 AFSDumpTraceFilesFnc();
2557 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2558 IN UCHAR FunctionCode,
2559 IN ULONG RequestFlags,
2560 IN AFSIoRun *IoRuns,
2562 IN AFSGatherIo *GatherIo)
2565 NTSTATUS ntStatus = STATUS_SUCCESS;
2566 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2567 AFSWorkItem *pWorkItem = NULL;
2572 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2575 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2576 AFS_TRACE_LEVEL_ERROR,
2577 "AFSQueueStartIos Failing request, in shutdown\n");
2579 try_return( ntStatus = STATUS_TOO_LATE);
2583 // Allocate our request structure and send it to the worker
2586 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2587 sizeof( AFSWorkItem),
2590 if( pWorkItem == NULL)
2593 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2594 AFS_TRACE_LEVEL_ERROR,
2595 "AFSQueueStartIos Failed to allocate work item\n");
2597 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2600 RtlZeroMemory( pWorkItem,
2601 sizeof( AFSWorkItem));
2603 KeInitializeEvent( &pWorkItem->Event,
2607 pWorkItem->Size = sizeof( AFSWorkItem);
2609 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2611 pWorkItem->RequestType = AFS_WORK_START_IOS;
2613 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2615 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2617 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2619 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2621 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2623 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2625 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2626 AFS_TRACE_LEVEL_VERBOSE,
2627 "AFSQueueStartIos Queuing IO Workitem %p\n",
2630 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2634 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2635 AFS_TRACE_LEVEL_VERBOSE,
2636 "AFSQueueStartIos Request complete Status %08lX\n",
2639 if( !NT_SUCCESS( ntStatus))
2642 if( pWorkItem != NULL)
2645 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2649 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2654 "EXCEPTION - AFSQueueStartIos\n");
2656 AFSDumpTraceFilesFnc();
2663 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2664 IN ULONG InvalidateReason)
2667 NTSTATUS ntStatus = STATUS_SUCCESS;
2668 AFSWorkItem *pWorkItem = NULL;
2673 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2674 sizeof(AFSWorkItem),
2676 if (NULL == pWorkItem)
2679 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2680 AFS_TRACE_LEVEL_ERROR,
2681 "AFSQueueInvalidateObject Failed to allocate work item\n");
2683 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2686 RtlZeroMemory( pWorkItem,
2687 sizeof(AFSWorkItem));
2689 pWorkItem->Size = sizeof( AFSWorkItem);
2691 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2693 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2695 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2697 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2698 AFS_TRACE_LEVEL_VERBOSE,
2699 "AFSQueueInvalidateObject Workitem %p\n",
2702 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2706 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2707 AFS_TRACE_LEVEL_VERBOSE,
2708 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2711 if( !NT_SUCCESS( ntStatus))
2714 if( pWorkItem != NULL)
2716 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2719 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2720 AFS_TRACE_LEVEL_ERROR,
2721 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2725 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2730 "EXCEPTION - AFSQueueInvalidateObject\n");
2732 AFSDumpTraceFilesFnc();