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"
43 AFSPostedDeferredWrite( IN PVOID Context1,
47 // Function: AFSInitializeWorkerPool
51 // This function initializes the worker thread pool
55 // A status is returned for the function
59 AFSInitializeWorkerPool()
62 NTSTATUS ntStatus = STATUS_SUCCESS;
63 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
64 AFSDeviceExt *pDevExt = NULL;
69 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
72 // Initialize the worker threads.
75 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
78 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
79 sizeof( AFSWorkQueueContext),
82 if( pCurrentWorker == NULL)
85 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
86 AFS_TRACE_LEVEL_ERROR,
87 "AFSInitializeWorkerPool Failed to allocate worker context\n");
89 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
94 RtlZeroMemory( pCurrentWorker,
95 sizeof( AFSWorkQueueContext));
97 ntStatus = AFSInitWorkerThread( pCurrentWorker,
98 (PKSTART_ROUTINE)AFSWorkerThread);
100 if( !NT_SUCCESS( ntStatus))
103 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
104 AFS_TRACE_LEVEL_ERROR,
105 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
107 ExFreePool( pCurrentWorker);
112 if( pDevExt->Specific.Library.PoolHead == NULL)
115 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
120 pLastWorker->fLink = pCurrentWorker;
123 pLastWorker = pCurrentWorker;
125 pDevExt->Specific.Library.WorkerCount++;
129 // If there was a failure but there is at least one worker, then go with it.
132 if( !NT_SUCCESS( ntStatus) &&
133 pDevExt->Specific.Library.WorkerCount == 0)
136 try_return( ntStatus);
139 ntStatus = STATUS_SUCCESS;
142 // Now our IO Worker queue
145 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
148 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
149 sizeof( AFSWorkQueueContext),
152 if( pCurrentWorker == NULL)
155 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
156 AFS_TRACE_LEVEL_ERROR,
157 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
159 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
164 RtlZeroMemory( pCurrentWorker,
165 sizeof( AFSWorkQueueContext));
167 ntStatus = AFSInitWorkerThread( pCurrentWorker,
168 (PKSTART_ROUTINE)AFSIOWorkerThread);
170 if( !NT_SUCCESS( ntStatus))
173 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
174 AFS_TRACE_LEVEL_ERROR,
175 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
177 ExFreePool( pCurrentWorker);
182 if( pDevExt->Specific.Library.IOPoolHead == NULL)
185 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
190 pLastWorker->fLink = pCurrentWorker;
193 pLastWorker = pCurrentWorker;
195 pDevExt->Specific.Library.IOWorkerCount++;
199 // If there was a failure but there is at least one worker, then go with it.
202 if( !NT_SUCCESS( ntStatus) &&
203 pDevExt->Specific.Library.IOWorkerCount == 0)
206 try_return( ntStatus);
211 if( !NT_SUCCESS( ntStatus))
215 // Failed to initialize the pool so tear it down
218 AFSRemoveWorkerPool();
226 // Function: AFSRemoveWorkerPool
230 // This function tears down the worker thread pool
234 // A status is returned for the function
238 AFSRemoveWorkerPool()
241 NTSTATUS ntStatus = STATUS_SUCCESS;
243 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
244 AFSDeviceExt *pDevExt = NULL;
246 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
249 // Loop through the workers shutting them down in two stages.
250 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
251 // stop processing requests. Second, call AFSShutdownWorkerThread()
252 // to wake the workers and wait for them to exit.
255 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
257 while( index < pDevExt->Specific.Library.WorkerCount)
260 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
262 pCurrentWorker = pCurrentWorker->fLink;
264 if ( pCurrentWorker == NULL)
273 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
277 while( index < pDevExt->Specific.Library.WorkerCount)
280 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
282 pNextWorker = pCurrentWorker->fLink;
284 ExFreePool( pCurrentWorker);
286 pCurrentWorker = pNextWorker;
288 if( pCurrentWorker == NULL)
297 pDevExt->Specific.Library.PoolHead = NULL;
300 // Loop through the IO workers shutting them down in two stages.
301 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
302 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
303 // to wake the workers and wait for them to exit.
306 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
310 while( index < pDevExt->Specific.Library.IOWorkerCount)
313 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
315 pCurrentWorker = pCurrentWorker->fLink;
317 if ( pCurrentWorker == NULL)
326 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
330 while( index < pDevExt->Specific.Library.IOWorkerCount)
333 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
335 pNextWorker = pCurrentWorker->fLink;
337 ExFreePool( pCurrentWorker);
339 pCurrentWorker = pNextWorker;
341 if( pCurrentWorker == NULL)
350 pDevExt->Specific.Library.IOPoolHead = NULL;
356 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
359 NTSTATUS ntStatus = STATUS_SUCCESS;
360 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
362 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
363 PKSTART_ROUTINE pStartRoutine = NULL;
369 if ( VolumeCB != AFSGlobalRoot)
372 return STATUS_INVALID_PARAMETER;
375 pStartRoutine = AFSPrimaryVolumeWorkerThread;
378 // Initialize the worker thread
381 KeInitializeEvent( &pWorker->WorkerThreadReady,
386 // Set the worker to process requests
389 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
395 ntStatus = PsCreateSystemThread( &hThread,
403 if( NT_SUCCESS( ntStatus))
406 ObReferenceObjectByHandle( hThread,
407 GENERIC_READ | GENERIC_WRITE,
410 (PVOID *)&pWorker->WorkerThreadObject,
413 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
419 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
424 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
435 // Function: AFSInitWorkerThread
439 // This function initializes a worker thread in the pool
443 // A status is returned for the function
447 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
448 IN PKSTART_ROUTINE WorkerRoutine)
451 NTSTATUS ntStatus = STATUS_SUCCESS;
455 // INitialize the worker signal thread
458 KeInitializeEvent( &PoolContext->WorkerThreadReady,
463 // Set the worker to process requests
466 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
472 ntStatus = PsCreateSystemThread( &Handle,
478 (void *)PoolContext);
480 if( NT_SUCCESS( ntStatus))
483 ObReferenceObjectByHandle( Handle,
484 GENERIC_READ | GENERIC_WRITE,
487 (PVOID *)&PoolContext->WorkerThreadObject,
490 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
503 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
506 NTSTATUS ntStatus = STATUS_SUCCESS;
507 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
510 // Clear the 'keep processing' flag
513 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
515 if( pWorker->WorkerThreadObject != NULL)
517 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
520 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
527 ObDereferenceObject( pWorker->WorkerThreadObject);
529 pWorker->WorkerThreadObject = NULL;
536 // Function: AFSShutdownWorkerThread
540 // This function shutsdown a worker thread in the pool
544 // A status is returned for the function
548 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
551 NTSTATUS ntStatus = STATUS_SUCCESS;
552 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
554 if( PoolContext->WorkerThreadObject != NULL)
557 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
561 // Wake up the thread if it is a sleep
564 KeSetEvent( &pControlDeviceExt->Specific.Control.WorkerQueueHasItems,
568 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
575 ObDereferenceObject( PoolContext->WorkerThreadObject);
577 PoolContext->WorkerThreadObject = NULL;
584 // Function: AFSShutdownIOWorkerThread
588 // This function shutsdown an IO worker thread in the pool
592 // A status is returned for the function
596 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
599 NTSTATUS ntStatus = STATUS_SUCCESS;
600 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
602 if( PoolContext->WorkerThreadObject != NULL)
605 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
609 // Wake up the thread if it is a sleep
612 KeSetEvent( &pControlDeviceExt->Specific.Control.IOWorkerQueueHasItems,
616 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
623 ObDereferenceObject( PoolContext->WorkerThreadObject);
625 PoolContext->WorkerThreadObject = NULL;
632 // Function: AFSWorkerThread
636 // This is the worker thread entry point.
640 // A status is returned for the function
644 AFSWorkerThread( IN PVOID Context)
647 NTSTATUS ntStatus = STATUS_SUCCESS;
648 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
649 AFSWorkItem *pWorkItem;
650 BOOLEAN freeWorkItem = TRUE;
651 AFSDeviceExt *pControlDevExt = NULL;
654 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
657 // Indicate that we are initialized and ready
660 KeSetEvent( &pPoolContext->WorkerThreadReady,
665 // Indicate we are initialized
668 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
670 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
676 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
679 if( !NT_SUCCESS( ntStatus))
682 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
683 AFS_TRACE_LEVEL_ERROR,
684 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
686 ntStatus = STATUS_SUCCESS;
691 pWorkItem = AFSRemoveWorkItem();
693 if( pWorkItem == NULL)
696 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
708 // Switch on the type of work item to process
711 switch( pWorkItem->RequestType)
714 case AFS_WORK_FLUSH_FCB:
717 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
718 &pWorkItem->AuthGroup);
720 if( !NT_SUCCESS( ntStatus))
723 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
724 &pWorkItem->AuthGroup,
728 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
730 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
735 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
738 AFSEnumerateGlobalRoot( NULL);
743 case AFS_WORK_INVALIDATE_OBJECT:
746 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
747 pWorkItem->Specific.Invalidate.InvalidateReason);
754 case AFS_WORK_START_IOS:
764 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
765 AFS_TRACE_LEVEL_ERROR,
766 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
774 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
777 ntStatus = STATUS_SUCCESS;
780 } // worker thread loop
782 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
784 // Wake up another worker so they too can exit
786 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
790 PsTerminateSystemThread( 0);
796 AFSIOWorkerThread( IN PVOID Context)
799 NTSTATUS ntStatus = STATUS_SUCCESS;
800 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
801 AFSWorkItem *pWorkItem;
802 BOOLEAN freeWorkItem = TRUE;
803 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
805 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
808 // Indicate that we are initialized and ready
811 KeSetEvent( &pPoolContext->WorkerThreadReady,
817 // Indicate we are initialized
820 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
822 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
828 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
831 if( !NT_SUCCESS( ntStatus))
834 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
835 AFS_TRACE_LEVEL_ERROR,
836 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
838 ntStatus = STATUS_SUCCESS;
843 pWorkItem = AFSRemoveIOWorkItem();
845 if( pWorkItem == NULL)
848 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
860 // Switch on the type of work item to process
863 switch( pWorkItem->RequestType)
866 case AFS_WORK_START_IOS:
869 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
872 // The final status is in the gather io
875 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
876 pWorkItem->Specific.CacheAccess.FunctionCode,
877 pWorkItem->Specific.CacheAccess.RequestFlags,
878 pWorkItem->Specific.CacheAccess.IoRuns,
879 pWorkItem->Specific.CacheAccess.RunCount,
880 pWorkItem->Specific.CacheAccess.GatherIo);
883 // Regardless of the status we we do the complete - there may
885 // Decrement the count - setting the event if we were told
886 // to. This may trigger completion.
889 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
896 case AFS_WORK_DEFERRED_WRITE:
899 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
900 pWorkItem->Specific.AsynchIo.Irp,
901 pWorkItem->Specific.AsynchIo.CallingProcess,
911 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
912 AFS_TRACE_LEVEL_ERROR,
913 "AFSIOWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
921 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
924 ntStatus = STATUS_SUCCESS;
927 } // worker thread loop
929 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
931 // Wake up another IOWorker so they too can exit
933 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
937 PsTerminateSystemThread( 0);
943 AFSExamineDirectory( IN AFSObjectInfoCB * pCurrentObject,
944 IN AFSDirectoryCB * pCurrentDirEntry)
948 AFSObjectInfoCB *pCurrentChildObject = NULL;
949 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
950 BOOLEAN bFcbBusy = FALSE;
953 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
955 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
956 AFS_TRACE_LEVEL_VERBOSE,
957 "AFSExamineDirectory Deleting DE %wZ Object %p\n",
958 &pCurrentDirEntry->NameInformation.FileName,
959 pCurrentChildObject);
961 AFSDeleteDirEntry( pCurrentObject,
964 if ( pCurrentChildObject != NULL)
968 // Acquire ObjectInfoLock shared here so as not to deadlock
969 // with an invalidation call from the service during AFSCleanupFcb
972 lCount = AFSObjectInfoIncrement( pCurrentChildObject,
973 AFS_OBJECT_REFERENCE_WORKER);
975 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
976 AFS_TRACE_LEVEL_VERBOSE,
977 "AFSExamineDirectory Increment count on object %p Cnt %d\n",
982 pCurrentChildObject->Fcb != NULL &&
983 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
987 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
988 // across an AFSCleanupFcb call since it can deadlock with an
989 // invalidation call from the service.
992 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
995 // Cannot hold a TreeLock across an AFSCleanupFcb call
996 // as it can deadlock with an invalidation ioctl initiated
999 // Dropping the TreeLock permits the
1000 // pCurrentObject->ObjectReferenceCount to change
1003 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1006 if ( ntStatus == STATUS_RETRY)
1012 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1016 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1019 lCount = AFSObjectInfoDecrement( pCurrentChildObject,
1020 AFS_OBJECT_REFERENCE_WORKER);
1022 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1023 AFS_TRACE_LEVEL_VERBOSE,
1024 "AFSExamineDirectory Decrement1 count on object %p Cnt %d\n",
1025 pCurrentChildObject,
1029 pCurrentChildObject->Fcb != NULL &&
1030 pCurrentChildObject->Fcb->OpenReferenceCount == 0)
1033 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1035 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1036 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1039 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1042 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1044 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1046 AFSDeleteObjectInfo( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1048 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1050 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1052 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1053 AFS_TRACE_LEVEL_VERBOSE,
1054 "AFSExamineDirectory (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1055 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1057 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1060 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1062 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1063 AFS_TRACE_LEVEL_VERBOSE,
1064 "AFSExamineDirectory Deleting object %p\n",
1065 pCurrentChildObject);
1067 AFSDeleteObjectInfo( &pCurrentChildObject);
1072 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1080 // Called with VolumeCB->ObjectInfoTree.TreeLock held shared.
1081 // The TreeLock will be released unless *pbReleaseVolumeLock is set to FALSE.
1085 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
1086 IN BOOLEAN bVolumeObject,
1087 IN OUT BOOLEAN * pbReleaseVolumeLock)
1089 NTSTATUS ntStatus = STATUS_SUCCESS;
1090 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1091 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1092 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
1093 AFSObjectInfoCB *pCurrentChildObject = NULL;
1094 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
1095 LARGE_INTEGER liCurrentTime;
1096 BOOLEAN bFcbBusy = FALSE;
1100 switch ( pCurrentObject->FileType) {
1102 case AFS_FILE_TYPE_DIRECTORY:
1105 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1112 // If this object is deleted then remove it from the parent, if we can
1115 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1116 pCurrentObject->ObjectReferenceCount <= 0 &&
1117 ( pCurrentObject->Fcb == NULL ||
1118 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1119 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1120 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1123 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1126 // Dropping the TreeLock permits the
1127 // pCurrentObject->ObjectReferenceCount to change
1130 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1134 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1137 if ( pCurrentObject->ObjectReferenceCount <= 0)
1140 AFSRemoveFcb( &pCurrentObject->Fcb);
1142 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1145 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1148 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1150 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1152 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1154 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1156 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1158 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1159 AFS_TRACE_LEVEL_VERBOSE,
1160 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1161 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1163 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1166 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1168 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1169 AFS_TRACE_LEVEL_VERBOSE,
1170 "AFSExamineObjectInfo Deleting deleted object %p\n",
1173 AFSDeleteObjectInfo( &pCurrentObject);
1178 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1181 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1186 *pbReleaseVolumeLock = FALSE;
1192 if ( pCurrentObject->Fcb != NULL &&
1193 pCurrentObject->Fcb->CcbListHead != NULL)
1198 for ( pCcb = pCurrentObject->Fcb->CcbListHead;
1200 pCcb = (AFSCcb *)pCcb->ListEntry.fLink)
1203 if ( pCcb->NameArray) {
1205 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1206 AFS_TRACE_LEVEL_VERBOSE,
1207 "AFSExamineObjectInfo Found Object %p Fcb %p Ccb %p\n",
1209 pCurrentObject->Fcb,
1217 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1218 ( pCurrentObject->Fcb != NULL &&
1219 pCurrentObject->Fcb->OpenReferenceCount > 0))
1225 if ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
1226 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1229 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1236 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1239 // Directory Entry Processing
1242 KeQueryTickCount( &liCurrentTime);
1244 while( pCurrentDirEntry != NULL)
1247 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1253 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1259 if ( pCurrentDirEntry->ObjectInformation != NULL)
1262 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1263 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1269 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1270 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1271 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1277 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1280 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1286 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1293 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1296 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1297 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1305 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1308 if( pCurrentDirEntry != NULL)
1311 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1316 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1318 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1321 // Now acquire the locks excl without deadlocking
1324 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1328 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1332 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1334 *pbReleaseVolumeLock = FALSE;
1339 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1342 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1344 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1349 KeQueryTickCount( &liCurrentTime);
1351 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1353 while( pCurrentDirEntry != NULL)
1356 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1362 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1368 if ( pCurrentDirEntry->ObjectInformation != NULL)
1371 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1372 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1378 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1379 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1380 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1386 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1389 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1395 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1402 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1405 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1406 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1414 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1417 if( pCurrentDirEntry != NULL)
1420 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1422 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1427 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1429 while( pCurrentDirEntry != NULL)
1432 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1434 AFSExamineDirectory( pCurrentObject,
1437 pCurrentDirEntry = pNextDirEntry;
1441 // Clear our enumerated flag on this object so we retrieve info again on next access
1444 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1446 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1448 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1454 // Try to grab the volume lock again ... no problem if we don't
1457 if( !AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1461 *pbReleaseVolumeLock = FALSE;
1467 else if ( bVolumeObject == FALSE)
1473 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1475 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1479 *pbReleaseVolumeLock = FALSE;
1484 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1487 KeQueryTickCount( &liCurrentTime);
1489 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1490 ( pCurrentObject->Fcb == NULL ||
1491 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1492 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1493 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1494 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1497 AFSRemoveFcb( &pCurrentObject->Fcb);
1499 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1501 AFSDeleteObjectInfo( &pCurrentObject);
1506 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1509 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1514 case AFS_FILE_TYPE_FILE:
1517 lCount = AFSObjectInfoIncrement( pCurrentObject,
1518 AFS_OBJECT_REFERENCE_WORKER);
1520 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1521 AFS_TRACE_LEVEL_VERBOSE,
1522 "AFSExamineObjectInfo Increment3 count on object %p Cnt %d\n",
1526 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1528 if( pCurrentObject->Fcb != NULL)
1532 // Dropping the TreeLock permits the
1533 // pCurrentObject->ObjectReferenceCount to change
1536 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1539 if ( ntStatus == STATUS_RETRY)
1546 bTemp = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1549 lCount = AFSObjectInfoDecrement( pCurrentObject,
1550 AFS_OBJECT_REFERENCE_WORKER);
1552 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1553 AFS_TRACE_LEVEL_VERBOSE,
1554 "AFSExamineObjectInfo Decrement3 count on object %p Cnt %d\n",
1559 if ( bTemp == FALSE)
1562 *pbReleaseVolumeLock = FALSE;
1567 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1570 KeQueryTickCount( &liCurrentTime);
1572 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1573 ( pCurrentObject->Fcb == NULL ||
1574 ( pCurrentObject->Fcb->OpenReferenceCount <= 0 &&
1575 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount <= 0)) &&
1576 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1577 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1578 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1581 AFSRemoveFcb( &pCurrentObject->Fcb);
1583 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1585 AFSDeleteObjectInfo( &pCurrentObject);
1590 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1593 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1600 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1602 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1606 *pbReleaseVolumeLock = FALSE;
1611 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1614 KeQueryTickCount( &liCurrentTime);
1616 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1617 ( pCurrentObject->Fcb == NULL ||
1618 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1619 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1620 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1621 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1624 AFSRemoveFcb( &pCurrentObject->Fcb);
1626 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1628 AFSDeleteObjectInfo( &pCurrentObject);
1633 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1636 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1645 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1647 NTSTATUS ntStatus = STATUS_SUCCESS;
1648 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1649 BOOLEAN bReleaseVolumeLock = FALSE;
1650 BOOLEAN bVolumeObject = FALSE;
1651 BOOLEAN bFcbBusy = FALSE;
1654 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1658 bReleaseVolumeLock = TRUE;
1660 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1664 while( pCurrentObject != NULL)
1667 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1670 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1673 // If the end of the VolumeCB ObjectInfo List is reached, then
1674 // the next ObjectInformationCB to examine is the one embedded within
1675 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1677 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1678 // is being examined.
1681 if( pNextObject == NULL &&
1682 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1685 pNextObject = &pVolumeCB->ObjectInformation;
1688 bVolumeObject = FALSE;
1693 lCount = AFSObjectInfoIncrement( pNextObject,
1694 AFS_OBJECT_REFERENCE_WORKER);
1696 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1697 AFS_TRACE_LEVEL_VERBOSE,
1698 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1708 bVolumeObject = TRUE;
1711 bFcbBusy = AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeLock);
1716 lCount = AFSObjectInfoDecrement( pNextObject,
1717 AFS_OBJECT_REFERENCE_WORKER);
1719 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1720 AFS_TRACE_LEVEL_VERBOSE,
1721 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1727 // If AFSExamineObjectInfo drops the VolumeLock before returning
1728 // we must halt processing of the Volume's ObjectInfo list.
1731 if ( bReleaseVolumeLock == FALSE)
1737 pCurrentObject = pNextObject;
1740 if( bReleaseVolumeLock)
1743 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1751 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1754 UNREFERENCED_PARAMETER(Context);
1755 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1756 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1757 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1758 LARGE_INTEGER DueTime;
1761 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1762 BOOLEAN bFcbBusy = FALSE;
1765 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1766 AFS_TRACE_LEVEL_VERBOSE,
1767 "AFSPrimaryVolumeWorkerThread Initialized\n");
1770 // Initialize the timer for the worker thread
1773 DueTime.QuadPart = -(5000);
1777 KeInitializeTimerEx( &Timer,
1778 SynchronizationTimer);
1780 KeSetTimerEx( &Timer,
1786 // Indicate that we are initialized and ready
1789 KeSetEvent( &pPoolContext->WorkerThreadReady,
1794 // Indicate we are initialized
1797 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1799 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1802 if ( bFcbBusy == FALSE)
1805 KeWaitForSingleObject( &Timer,
1818 // This is the primary volume worker so it will traverse the volume list
1819 // looking for cleanup or volumes requiring private workers
1822 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1825 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1827 while( pVolumeCB != NULL)
1830 if( pVolumeCB == AFSGlobalRoot ||
1831 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1835 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1840 if( pVolumeCB->ObjectInfoListHead == NULL)
1843 AFSReleaseResource( pVolumeCB->VolumeLock);
1845 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1847 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1850 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1853 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1857 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1859 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1861 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1866 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1868 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1872 // If VolumeCB is idle, the Volume can be garbage collected
1875 if( pVolumeCB->ObjectInfoListHead == NULL &&
1876 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1877 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1878 pVolumeCB->VolumeReferenceCount == 0 &&
1879 ( pVolumeCB->RootFcb == NULL ||
1880 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1881 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1884 AFSRemoveRootFcb( pVolumeCB);
1886 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1888 AFSRemoveVolume( pVolumeCB);
1893 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1895 AFSReleaseResource( pVolumeCB->VolumeLock);
1898 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1900 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1902 pVolumeCB = pNextVolume;
1908 // Don't need this lock anymore now that we have a volume cb to work with
1911 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1914 // For now we only need the volume lock shared
1917 AFSConvertToShared( pVolumeCB->VolumeLock);
1919 AFSExamineVolume( pVolumeCB);
1925 AFSReleaseResource( pVolumeCB->VolumeLock);
1927 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1930 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1933 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1935 } // worker thread loop
1937 KeCancelTimer( &Timer);
1939 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1941 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1942 AFS_TRACE_LEVEL_VERBOSE,
1943 "AFSPrimaryVolumeWorkerThread Exiting\n");
1945 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1950 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1955 PsTerminateSystemThread( 0);
1961 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1964 NTSTATUS ntStatus = STATUS_SUCCESS;
1965 AFSDeviceExt *pControlDevExt = NULL;
1968 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1970 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1971 AFS_TRACE_LEVEL_VERBOSE,
1972 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1973 &pControlDevExt->Specific.Control.QueueLock,
1974 PsGetCurrentThread());
1976 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1979 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1981 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1982 AFS_TRACE_LEVEL_VERBOSE,
1983 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1987 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1990 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1995 pControlDevExt->Specific.Control.QueueHead = WorkItem;
1998 WorkItem->next = NULL;
1999 pControlDevExt->Specific.Control.QueueTail = WorkItem;
2001 // indicate that the queue has nodes
2002 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2006 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2012 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
2015 NTSTATUS ntStatus = STATUS_SUCCESS;
2016 AFSDeviceExt *pControlDevExt = NULL;
2019 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2021 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2022 AFS_TRACE_LEVEL_VERBOSE,
2023 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2024 &pControlDevExt->Specific.Control.IOQueueLock,
2025 PsGetCurrentThread());
2027 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2030 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2032 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2033 AFS_TRACE_LEVEL_VERBOSE,
2034 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
2038 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
2041 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
2046 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
2049 WorkItem->next = NULL;
2050 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
2052 // indicate that the queue has nodes
2053 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2057 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2063 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2066 NTSTATUS ntStatus = STATUS_SUCCESS;
2067 AFSDeviceExt *pControlDevExt = NULL;
2070 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2072 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2073 AFS_TRACE_LEVEL_VERBOSE,
2074 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2075 &pControlDevExt->Specific.Control.QueueLock,
2076 PsGetCurrentThread());
2078 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2081 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2083 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2085 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2087 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2088 AFS_TRACE_LEVEL_VERBOSE,
2089 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2094 // indicate that the queue has nodes
2097 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2101 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2110 AFSWorkItem *pWorkItem = NULL;
2111 AFSDeviceExt *pControlDevExt = NULL;
2114 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2116 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2117 AFS_TRACE_LEVEL_VERBOSE,
2118 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2119 &pControlDevExt->Specific.Control.QueueLock,
2120 PsGetCurrentThread());
2122 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2125 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2128 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2130 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2132 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2133 AFS_TRACE_LEVEL_VERBOSE,
2134 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2137 PsGetCurrentThreadId());
2139 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2141 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2144 pControlDevExt->Specific.Control.QueueTail = NULL;
2150 // Wake up another worker
2153 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2159 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2165 AFSRemoveIOWorkItem()
2168 AFSWorkItem *pWorkItem = NULL;
2169 AFSDeviceExt *pControlDevExt = NULL;
2172 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2174 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2175 AFS_TRACE_LEVEL_VERBOSE,
2176 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2177 &pControlDevExt->Specific.Control.IOQueueLock,
2178 PsGetCurrentThread());
2180 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2183 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2186 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2188 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2190 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2191 AFS_TRACE_LEVEL_VERBOSE,
2192 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2195 PsGetCurrentThreadId());
2197 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2199 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2202 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2208 // Wake up another worker
2211 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2217 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2223 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2226 NTSTATUS ntStatus = STATUS_SUCCESS;
2227 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2230 // Submit the work item to the worker
2233 ntStatus = AFSInsertWorkitem( WorkItem);
2239 // Sync request so block on the work item event
2242 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2253 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2256 NTSTATUS ntStatus = STATUS_SUCCESS;
2257 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2260 // Submit the work item to the worker
2263 ntStatus = AFSInsertIOWorkitem( WorkItem);
2269 // Sync request so block on the work item event
2272 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2283 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2286 NTSTATUS ntStatus = STATUS_SUCCESS;
2287 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2290 // Submit the work item to the worker
2293 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2299 // Sync request so block on the work item event
2302 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2313 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2317 NTSTATUS ntStatus = STATUS_SUCCESS;
2318 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2319 AFSWorkItem *pWorkItem = NULL;
2325 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2326 AFS_TRACE_LEVEL_VERBOSE,
2327 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2328 Fcb->ObjectInformation->FileId.Cell,
2329 Fcb->ObjectInformation->FileId.Volume,
2330 Fcb->ObjectInformation->FileId.Vnode,
2331 Fcb->ObjectInformation->FileId.Unique);
2334 // Increment our flush count here just to keep the number of items in the
2335 // queue down. We'll decrement it just below.
2338 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2343 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2344 AFS_TRACE_LEVEL_VERBOSE,
2345 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2346 Fcb->ObjectInformation->FileId.Cell,
2347 Fcb->ObjectInformation->FileId.Volume,
2348 Fcb->ObjectInformation->FileId.Vnode,
2349 Fcb->ObjectInformation->FileId.Unique);
2351 try_return( ntStatus);
2354 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2357 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2358 AFS_TRACE_LEVEL_ERROR,
2359 "AFSQueueFlushExtents Failing request, in shutdown\n");
2361 try_return( ntStatus = STATUS_TOO_LATE);
2365 // Allocate our request structure and send it to the worker
2368 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2369 sizeof( AFSWorkItem),
2372 if( pWorkItem == NULL)
2375 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2376 AFS_TRACE_LEVEL_ERROR,
2377 "AFSQueueFlushExtents Failed to allocate work item\n");
2379 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2382 RtlZeroMemory( pWorkItem,
2383 sizeof( AFSWorkItem));
2385 pWorkItem->Size = sizeof( AFSWorkItem);
2387 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2389 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2391 if ( AuthGroup == NULL)
2394 RtlZeroMemory( &pWorkItem->AuthGroup,
2397 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2400 &pWorkItem->AuthGroup);
2404 RtlCopyMemory( &pWorkItem->AuthGroup,
2409 pWorkItem->Specific.Fcb.Fcb = Fcb;
2411 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2413 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2414 AFS_TRACE_LEVEL_VERBOSE,
2415 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2419 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2420 AFS_TRACE_LEVEL_VERBOSE,
2421 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2423 Fcb->ObjectInformation->FileId.Cell,
2424 Fcb->ObjectInformation->FileId.Volume,
2425 Fcb->ObjectInformation->FileId.Vnode,
2426 Fcb->ObjectInformation->FileId.Unique);
2428 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2432 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2433 AFS_TRACE_LEVEL_VERBOSE,
2434 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2435 Fcb->ObjectInformation->FileId.Cell,
2436 Fcb->ObjectInformation->FileId.Volume,
2437 Fcb->ObjectInformation->FileId.Vnode,
2438 Fcb->ObjectInformation->FileId.Unique,
2442 // Remove the count we added above
2445 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2447 ASSERT( lCount >= 0);
2452 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2457 if( !NT_SUCCESS( ntStatus))
2460 if( pWorkItem != NULL)
2463 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2465 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2468 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2469 AFS_TRACE_LEVEL_ERROR,
2470 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2473 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2478 "EXCEPTION - AFSQueueFlushExtents\n");
2480 AFSDumpTraceFilesFnc();
2487 AFSQueueGlobalRootEnumeration()
2490 NTSTATUS ntStatus = STATUS_SUCCESS;
2491 AFSWorkItem *pWorkItem = NULL;
2496 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2497 sizeof(AFSWorkItem),
2499 if (NULL == pWorkItem)
2502 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2503 AFS_TRACE_LEVEL_ERROR,
2504 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2506 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2509 RtlZeroMemory( pWorkItem,
2510 sizeof(AFSWorkItem));
2512 pWorkItem->Size = sizeof( AFSWorkItem);
2514 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2516 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2517 AFS_TRACE_LEVEL_VERBOSE,
2518 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2521 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2525 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2526 AFS_TRACE_LEVEL_VERBOSE,
2527 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2530 if( !NT_SUCCESS( ntStatus))
2533 if( pWorkItem != NULL)
2536 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2539 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2540 AFS_TRACE_LEVEL_ERROR,
2541 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2545 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2550 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2552 AFSDumpTraceFilesFnc();
2559 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2560 IN UCHAR FunctionCode,
2561 IN ULONG RequestFlags,
2562 IN AFSIoRun *IoRuns,
2564 IN AFSGatherIo *GatherIo)
2567 NTSTATUS ntStatus = STATUS_SUCCESS;
2568 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2569 AFSWorkItem *pWorkItem = NULL;
2574 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2577 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2578 AFS_TRACE_LEVEL_ERROR,
2579 "AFSQueueStartIos Failing request, in shutdown\n");
2581 try_return( ntStatus = STATUS_TOO_LATE);
2585 // Allocate our request structure and send it to the worker
2588 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2589 sizeof( AFSWorkItem),
2592 if( pWorkItem == NULL)
2595 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2596 AFS_TRACE_LEVEL_ERROR,
2597 "AFSQueueStartIos Failed to allocate work item\n");
2599 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2602 RtlZeroMemory( pWorkItem,
2603 sizeof( AFSWorkItem));
2605 KeInitializeEvent( &pWorkItem->Event,
2609 pWorkItem->Size = sizeof( AFSWorkItem);
2611 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2613 pWorkItem->RequestType = AFS_WORK_START_IOS;
2615 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2617 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2619 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2621 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2623 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2625 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2627 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2628 AFS_TRACE_LEVEL_VERBOSE,
2629 "AFSQueueStartIos Queuing IO Workitem %p\n",
2632 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2636 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2637 AFS_TRACE_LEVEL_VERBOSE,
2638 "AFSQueueStartIos Request complete Status %08lX\n",
2641 if( !NT_SUCCESS( ntStatus))
2644 if( pWorkItem != NULL)
2647 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2651 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2656 "EXCEPTION - AFSQueueStartIos\n");
2658 AFSDumpTraceFilesFnc();
2665 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2666 IN ULONG InvalidateReason)
2669 NTSTATUS ntStatus = STATUS_SUCCESS;
2670 AFSWorkItem *pWorkItem = NULL;
2675 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2676 sizeof(AFSWorkItem),
2678 if (NULL == pWorkItem)
2681 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2682 AFS_TRACE_LEVEL_ERROR,
2683 "AFSQueueInvalidateObject Failed to allocate work item\n");
2685 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2688 RtlZeroMemory( pWorkItem,
2689 sizeof(AFSWorkItem));
2691 pWorkItem->Size = sizeof( AFSWorkItem);
2693 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2695 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2697 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2699 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2700 AFS_TRACE_LEVEL_VERBOSE,
2701 "AFSQueueInvalidateObject Workitem %p\n",
2704 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2708 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2709 AFS_TRACE_LEVEL_VERBOSE,
2710 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2713 if( !NT_SUCCESS( ntStatus))
2716 if( pWorkItem != NULL)
2718 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2721 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2722 AFS_TRACE_LEVEL_ERROR,
2723 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2727 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2732 "EXCEPTION - AFSQueueInvalidateObject\n");
2734 AFSDumpTraceFilesFnc();
2741 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2742 IN PFILE_OBJECT FileObject,
2743 IN HANDLE CallingUser,
2745 IN ULONG BytesToWrite,
2746 IN BOOLEAN bRetrying)
2748 NTSTATUS ntStatus = STATUS_SUCCESS;
2749 AFSWorkItem *pWorkItem = NULL;
2755 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2759 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2762 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2763 AFS_TRACE_LEVEL_ERROR,
2764 "%s Could not pin user memory item\n",
2767 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2770 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2771 sizeof(AFSWorkItem),
2774 if (NULL == pWorkItem)
2777 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2778 AFS_TRACE_LEVEL_ERROR,
2779 "%s Failed to allocate work item\n",
2782 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2785 RtlZeroMemory( pWorkItem,
2786 sizeof(AFSWorkItem));
2788 pWorkItem->Size = sizeof( AFSWorkItem);
2790 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2792 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2794 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2796 pWorkItem->Specific.AsynchIo.Irp = Irp;
2798 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2799 AFS_TRACE_LEVEL_VERBOSE,
2804 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2806 IoMarkIrpPending(Irp);
2808 ntStatus = STATUS_PENDING;
2810 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2815 "EXCEPTION - %s \n",
2818 ntStatus = GetExceptionCode();
2823 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2824 AFS_TRACE_LEVEL_VERBOSE,
2825 "%s complete Status %08lX\n",
2829 if( !NT_SUCCESS( ntStatus))
2832 if( pWorkItem != NULL)
2835 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2838 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2839 AFS_TRACE_LEVEL_ERROR,
2840 "%s Failed to queue request Status %08lX\n",
2850 AFSPostedDeferredWrite( IN PVOID Context1,
2853 UNREFERENCED_PARAMETER( Context2);
2856 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2858 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2859 AFS_TRACE_LEVEL_ERROR,
2864 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2866 if (!NT_SUCCESS( ntStatus))
2869 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2871 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2873 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2874 AFS_TRACE_LEVEL_ERROR,
2875 "%s (%p) Failed to queue request Status %08lX\n",
2877 pWorkItem->Specific.AsynchIo.Irp,