2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 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
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // File: AFSWorker.cpp
37 #include "AFSCommon.h"
41 AFSPostedDeferredWrite( IN PVOID Context1,
45 // Function: AFSInitializeWorkerPool
49 // This function initializes the worker thread pool
53 // A status is returned for the function
57 AFSInitializeWorkerPool()
60 NTSTATUS ntStatus = STATUS_SUCCESS;
61 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
62 AFSDeviceExt *pDevExt = NULL;
67 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
70 // Initialize the worker threads.
73 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
76 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
77 sizeof( AFSWorkQueueContext),
80 if( pCurrentWorker == NULL)
83 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
84 AFS_TRACE_LEVEL_ERROR,
85 "AFSInitializeWorkerPool Failed to allocate worker context\n"));
87 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
92 RtlZeroMemory( pCurrentWorker,
93 sizeof( AFSWorkQueueContext));
95 ntStatus = AFSInitWorkerThread( pCurrentWorker,
96 (PKSTART_ROUTINE)AFSWorkerThread);
98 if( !NT_SUCCESS( ntStatus))
101 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
102 AFS_TRACE_LEVEL_ERROR,
103 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n",
106 AFSLibExFreePoolWithTag( 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 AFSDbgTrace(( 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 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
174 AFS_TRACE_LEVEL_ERROR,
175 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n",
178 AFSLibExFreePoolWithTag( pCurrentWorker,
184 if( pDevExt->Specific.Library.IOPoolHead == NULL)
187 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
192 pLastWorker->fLink = pCurrentWorker;
195 pLastWorker = pCurrentWorker;
197 pDevExt->Specific.Library.IOWorkerCount++;
201 // If there was a failure but there is at least one worker, then go with it.
204 if( !NT_SUCCESS( ntStatus) &&
205 pDevExt->Specific.Library.IOWorkerCount == 0)
208 try_return( ntStatus);
213 if( !NT_SUCCESS( ntStatus))
217 // Failed to initialize the pool so tear it down
220 AFSRemoveWorkerPool();
228 // Function: AFSRemoveWorkerPool
232 // This function tears down the worker thread pool
236 // A status is returned for the function
240 AFSRemoveWorkerPool()
243 NTSTATUS ntStatus = STATUS_SUCCESS;
245 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
246 AFSDeviceExt *pDevExt = NULL;
248 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
251 // Loop through the workers shutting them down in two stages.
252 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
253 // stop processing requests. Second, call AFSShutdownWorkerThread()
254 // to wake the workers and wait for them to exit.
257 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
259 while( index < pDevExt->Specific.Library.WorkerCount)
262 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
264 pCurrentWorker = pCurrentWorker->fLink;
266 if ( pCurrentWorker == NULL)
275 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
279 while( index < pDevExt->Specific.Library.WorkerCount)
282 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
284 pNextWorker = pCurrentWorker->fLink;
286 AFSLibExFreePoolWithTag( pCurrentWorker,
289 pCurrentWorker = pNextWorker;
291 if( pCurrentWorker == NULL)
300 pDevExt->Specific.Library.PoolHead = NULL;
303 // Loop through the IO workers shutting them down in two stages.
304 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
305 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
306 // to wake the workers and wait for them to exit.
309 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
313 while( index < pDevExt->Specific.Library.IOWorkerCount)
316 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
318 pCurrentWorker = pCurrentWorker->fLink;
320 if ( pCurrentWorker == NULL)
329 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
333 while( index < pDevExt->Specific.Library.IOWorkerCount)
336 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
338 pNextWorker = pCurrentWorker->fLink;
340 AFSLibExFreePoolWithTag( pCurrentWorker,
343 pCurrentWorker = pNextWorker;
345 if( pCurrentWorker == NULL)
354 pDevExt->Specific.Library.IOPoolHead = NULL;
360 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
363 NTSTATUS ntStatus = STATUS_SUCCESS;
364 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
366 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
367 PKSTART_ROUTINE pStartRoutine = NULL;
373 if ( VolumeCB != AFSGlobalRoot)
376 return STATUS_INVALID_PARAMETER;
379 pStartRoutine = AFSPrimaryVolumeWorkerThread;
382 // Initialize the worker thread
385 KeInitializeEvent( &pWorker->WorkerThreadReady,
390 // Set the worker to process requests
393 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
399 ntStatus = PsCreateSystemThread( &hThread,
407 if( NT_SUCCESS( ntStatus))
410 ObReferenceObjectByHandle( hThread,
411 GENERIC_READ | GENERIC_WRITE,
414 (PVOID *)&pWorker->WorkerThreadObject,
417 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
423 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
428 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
439 // Function: AFSInitWorkerThread
443 // This function initializes a worker thread in the pool
447 // A status is returned for the function
451 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
452 IN PKSTART_ROUTINE WorkerRoutine)
455 NTSTATUS ntStatus = STATUS_SUCCESS;
459 // INitialize the worker signal thread
462 KeInitializeEvent( &PoolContext->WorkerThreadReady,
467 // Set the worker to process requests
470 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
476 ntStatus = PsCreateSystemThread( &Handle,
482 (void *)PoolContext);
484 if( NT_SUCCESS( ntStatus))
487 ObReferenceObjectByHandle( Handle,
488 GENERIC_READ | GENERIC_WRITE,
491 (PVOID *)&PoolContext->WorkerThreadObject,
494 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
507 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
510 NTSTATUS ntStatus = STATUS_SUCCESS;
511 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
514 // Clear the 'keep processing' flag
517 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
519 if( pWorker->WorkerThreadObject != NULL)
521 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
524 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
531 ObDereferenceObject( pWorker->WorkerThreadObject);
533 pWorker->WorkerThreadObject = NULL;
540 // Function: AFSShutdownWorkerThread
544 // This function shutsdown a worker thread in the pool
548 // A status is returned for the function
552 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
555 NTSTATUS ntStatus = STATUS_SUCCESS;
556 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
558 if( PoolContext->WorkerThreadObject != NULL)
561 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
565 // Wake up the thread if it is a sleep
568 KeSetEvent( &pControlDeviceExt->Specific.Control.WorkerQueueHasItems,
572 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
579 ObDereferenceObject( PoolContext->WorkerThreadObject);
581 PoolContext->WorkerThreadObject = NULL;
588 // Function: AFSShutdownIOWorkerThread
592 // This function shutsdown an IO worker thread in the pool
596 // A status is returned for the function
600 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
603 NTSTATUS ntStatus = STATUS_SUCCESS;
604 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
606 if( PoolContext->WorkerThreadObject != NULL)
609 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
613 // Wake up the thread if it is a sleep
616 KeSetEvent( &pControlDeviceExt->Specific.Control.IOWorkerQueueHasItems,
620 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
627 ObDereferenceObject( PoolContext->WorkerThreadObject);
629 PoolContext->WorkerThreadObject = NULL;
636 // Function: AFSWorkerThread
640 // This is the worker thread entry point.
644 // A status is returned for the function
648 AFSWorkerThread( IN PVOID Context)
651 NTSTATUS ntStatus = STATUS_SUCCESS;
652 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
653 AFSWorkItem *pWorkItem;
654 BOOLEAN freeWorkItem = TRUE;
655 AFSDeviceExt *pControlDevExt = NULL;
658 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
661 // Indicate that we are initialized and ready
664 KeSetEvent( &pPoolContext->WorkerThreadReady,
669 // Indicate we are initialized
672 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
674 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
680 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
683 if( !NT_SUCCESS( ntStatus))
686 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
687 AFS_TRACE_LEVEL_ERROR,
688 "AFSWorkerThread Wait for queue items failed Status %08lX\n",
691 ntStatus = STATUS_SUCCESS;
696 pWorkItem = AFSRemoveWorkItem();
698 if( pWorkItem == NULL)
701 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
713 // Switch on the type of work item to process
716 switch( pWorkItem->RequestType)
719 case AFS_WORK_FLUSH_FCB:
722 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
723 &pWorkItem->AuthGroup);
725 if( !NT_SUCCESS( ntStatus))
728 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
729 &pWorkItem->AuthGroup,
733 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
735 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
740 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
743 AFSEnumerateGlobalRoot( NULL);
748 case AFS_WORK_INVALIDATE_OBJECT:
751 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
752 pWorkItem->Specific.Invalidate.InvalidateReason);
759 case AFS_WORK_START_IOS:
769 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
770 AFS_TRACE_LEVEL_ERROR,
771 "AFSWorkerThread Unknown request type %d\n",
772 pWorkItem->RequestType));
780 AFSExFreePoolWithTag( pWorkItem,
784 ntStatus = STATUS_SUCCESS;
787 } // worker thread loop
789 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
791 // Wake up another worker so they too can exit
793 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
797 PsTerminateSystemThread( 0);
803 AFSIOWorkerThread( IN PVOID Context)
806 NTSTATUS ntStatus = STATUS_SUCCESS;
807 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
808 AFSWorkItem *pWorkItem;
809 BOOLEAN freeWorkItem = TRUE;
810 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
812 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
815 // Indicate that we are initialized and ready
818 KeSetEvent( &pPoolContext->WorkerThreadReady,
824 // Indicate we are initialized
827 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
829 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
835 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
838 if( !NT_SUCCESS( ntStatus))
841 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
842 AFS_TRACE_LEVEL_ERROR,
843 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n",
846 ntStatus = STATUS_SUCCESS;
851 pWorkItem = AFSRemoveIOWorkItem();
853 if( pWorkItem == NULL)
856 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
868 // Switch on the type of work item to process
871 switch( pWorkItem->RequestType)
874 case AFS_WORK_START_IOS:
877 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
880 // The final status is in the gather io
883 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
884 pWorkItem->Specific.CacheAccess.FunctionCode,
885 pWorkItem->Specific.CacheAccess.RequestFlags,
886 pWorkItem->Specific.CacheAccess.IoRuns,
887 pWorkItem->Specific.CacheAccess.RunCount,
888 pWorkItem->Specific.CacheAccess.GatherIo);
891 // Regardless of the status we we do the complete - there may
893 // Decrement the count - setting the event if we were told
894 // to. This may trigger completion.
897 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
904 case AFS_WORK_DEFERRED_WRITE:
907 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
908 pWorkItem->Specific.AsynchIo.Irp,
909 pWorkItem->Specific.AsynchIo.CallingProcess,
919 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
920 AFS_TRACE_LEVEL_ERROR,
921 "AFSIOWorkerThread Unknown request type %d\n",
922 pWorkItem->RequestType));
930 AFSLibExFreePoolWithTag( pWorkItem,
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( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
947 PsTerminateSystemThread( 0);
953 // Called with VolumeCB->ObjectInfoTree.TreeLock held exclusive.
954 // pCurrentObject->ObjectReferenceCount is incremented by the caller.
956 // The *pbReleaseVolumeLock is set to FALSE if the TreeLock is dropped
959 // pCurrentObject must either be destroyed or the reference count
960 // decremented before returning.
964 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
965 IN BOOLEAN bVolumeObject,
966 IN OUT BOOLEAN * pbReleaseVolumeLock)
968 NTSTATUS ntStatus = STATUS_SUCCESS;
969 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
970 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
971 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
972 AFSObjectInfoCB *pCurrentChildObject = NULL;
973 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
974 LARGE_INTEGER liCurrentTime;
981 ASSERT( ExIsResourceAcquiredExclusiveLite( pVolumeCB->ObjectInfoTree.TreeLock));
983 switch ( pCurrentObject->FileType)
986 case AFS_FILE_TYPE_DIRECTORY:
989 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
992 try_return( ntStatus);
996 // If this object is deleted then remove it from the parent, if we can
999 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED))
1002 if ( pCurrentObject->ObjectReferenceCount == 1 &&
1003 ( pCurrentObject->Fcb == NULL ||
1004 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1005 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1006 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1009 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1012 if ( pCurrentObject->Fcb != NULL)
1015 AFSRemoveFcb( &pCurrentObject->Fcb);
1018 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1021 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1024 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1026 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1028 lCount = AFSObjectInfoDecrement( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1029 AFS_OBJECT_REFERENCE_PIOCTL);
1031 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1032 AFS_TRACE_LEVEL_VERBOSE,
1033 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1034 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1037 ASSERT( lCount == 0);
1042 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1045 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1047 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged,
1048 AFS_DIR_ENTRY_NP_TAG);
1050 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1051 AFS_TRACE_LEVEL_VERBOSE,
1052 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1053 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB));
1055 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB,
1058 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB = NULL;
1061 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1063 lCount = AFSObjectInfoDecrement( pCurrentObject,
1064 AFS_OBJECT_REFERENCE_WORKER);
1066 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSExamineObjectInfo Decrement1 count on object %p Cnt %d\n",
1072 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1073 AFS_TRACE_LEVEL_VERBOSE,
1074 "AFSExamineObjectInfo Deleting deleted object %p\n",
1078 // The CurrentReferenceCount must be zero or we would not
1079 // have gotten this far. It is safe to delete the ObjectInfoCB.
1082 AFSDeleteObjectInfo( &pCurrentObject);
1086 // Finished processing the AFS_OBJECT_FLAGS_DELETED case.
1089 try_return( ntStatus);
1093 // pCurrentObject not marked Deleted.
1096 if ( pCurrentObject->Fcb != NULL &&
1097 pCurrentObject->Fcb->CcbListHead != NULL)
1100 try_return( ntStatus);
1103 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1104 ( pCurrentObject->Fcb != NULL &&
1105 pCurrentObject->Fcb->OpenReferenceCount > 0))
1108 try_return( ntStatus);
1111 if ( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1112 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1116 // Directory Entry Processing
1118 // First pass is performed with the TreeLock held shared.
1119 // If we detect any objects in use, we give up quickly without
1120 // making any changes and without blocking other threads.
1121 // The second pass is performed with the TreeLock held exclusive
1122 // so deletions can take place.
1125 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1129 try_return( ntStatus);
1132 KeQueryTickCount( &liCurrentTime);
1134 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1136 while( pCurrentDirEntry != NULL)
1139 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1140 pCurrentDirEntry->NameArrayReferenceCount > 0)
1143 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1145 try_return( ntStatus);
1148 if ( pCurrentDirEntry->ObjectInformation != NULL)
1151 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1152 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1155 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1157 try_return( ntStatus);
1160 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1161 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1162 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1165 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1167 try_return( ntStatus);
1170 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1173 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1179 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1186 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1189 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1190 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1198 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1201 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1203 if( pCurrentDirEntry != NULL)
1206 try_return( ntStatus);
1210 // Attempt the second pass with the TreeLock held exclusive.
1211 // The the TreeLock cannot be obtained without blocking it means that
1212 // the directory is in active use, so do nothing.
1215 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1219 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1222 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1224 try_return( ntStatus);
1227 KeQueryTickCount( &liCurrentTime);
1229 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1231 while( pCurrentDirEntry != NULL)
1234 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1240 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1246 if ( pCurrentDirEntry->ObjectInformation != NULL)
1249 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1250 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1256 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1257 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1258 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1264 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1267 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1273 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1280 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1283 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1284 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1292 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1295 if( pCurrentDirEntry != NULL)
1299 // At least one entry in the directory is actively in use.
1300 // Drop the lock and exit without removing anything.
1303 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1305 try_return( ntStatus);
1309 // Third pass, process each directory entry and remove what we can.
1310 // The VolumeCB TreeLock and the ObjectInfo TreeLock are still held exclusive.
1313 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1315 while( pCurrentDirEntry != NULL)
1318 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1321 // Delete the DirectoryCB which in turn removes the DIRENTRY reference
1322 // count from the associated ObjectInfoCB. The reference count held above
1323 // may now be the only one left.
1326 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1327 AFS_TRACE_LEVEL_VERBOSE,
1328 "AFSExamineObjectInfo Deleting DE %wZ Object %p\n",
1329 &pCurrentDirEntry->NameInformation.FileName,
1330 pCurrentDirEntry->ObjectInformation));
1332 AFSDeleteDirEntry( pCurrentObject,
1335 pCurrentDirEntry = pNextDirEntry;
1339 // Clear our enumerated flag on this object so we retrieve info again on next access
1342 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1344 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1347 else if ( bVolumeObject == FALSE)
1353 if( pCurrentObject->ObjectReferenceCount > 1 ||
1354 pCurrentObject->Fcb != NULL &&
1355 pCurrentObject->Fcb->OpenReferenceCount > 0)
1358 try_return( ntStatus);
1361 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1364 KeQueryTickCount( &liCurrentTime);
1366 if( pCurrentObject->ObjectReferenceCount == 1 &&
1367 ( pCurrentObject->Fcb == NULL ||
1368 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1369 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1370 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1371 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1374 AFSRemoveFcb( &pCurrentObject->Fcb);
1376 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1378 lCount = AFSObjectInfoDecrement( pCurrentObject,
1379 AFS_OBJECT_REFERENCE_WORKER);
1381 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1382 AFS_TRACE_LEVEL_VERBOSE,
1383 "AFSExamineObjectInfo Decrement4 count on object %p Cnt %d\n",
1388 // The Volume TreeLock is held exclusive. Therefore, the ObjectReferenceCount
1389 // cannot change. It is therefore safe to delete the ObjectInfoCB
1392 AFSDeleteObjectInfo( &pCurrentObject);
1397 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1404 case AFS_FILE_TYPE_FILE:
1407 if( pCurrentObject->ObjectReferenceCount > 1 ||
1408 pCurrentObject->Fcb != NULL &&
1409 pCurrentObject->Fcb->OpenReferenceCount > 0)
1412 try_return( ntStatus);
1415 if( pCurrentObject->Fcb != NULL)
1418 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1421 // Dropping the VolumeCB TreeLock permits the
1422 // pCurrentObject->ObjectReferenceCount to change.
1423 // But it cannot be held across the AFSCleanupFcb
1427 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1430 if (!AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1434 *pbReleaseVolumeLock = FALSE;
1437 if ( ntStatus == STATUS_RETRY ||
1438 *pbReleaseVolumeLock == FALSE)
1442 // The Fcb is in use.
1445 try_return( ntStatus);
1450 // VolumeCB is held exclusive
1453 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1456 KeQueryTickCount( &liCurrentTime);
1458 if( pCurrentObject->ObjectReferenceCount == 1 &&
1459 ( pCurrentObject->Fcb == NULL ||
1460 ( pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1461 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount == 0)) &&
1462 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1463 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1464 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1467 AFSRemoveFcb( &pCurrentObject->Fcb);
1469 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1471 lCount = AFSObjectInfoDecrement( pCurrentObject,
1472 AFS_OBJECT_REFERENCE_WORKER);
1474 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1475 AFS_TRACE_LEVEL_VERBOSE,
1476 "AFSExamineObjectInfo Decrement5 count on object %p Cnt %d\n",
1481 // The VolumeCB TreeLock is held exclusive so the
1482 // ObjectReferenceCount cannot change.
1485 AFSDeleteObjectInfo( &pCurrentObject);
1490 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1499 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1502 KeQueryTickCount( &liCurrentTime);
1504 if( pCurrentObject->ObjectReferenceCount == 1 &&
1505 ( pCurrentObject->Fcb == NULL ||
1506 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1507 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1508 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1509 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1512 AFSRemoveFcb( &pCurrentObject->Fcb);
1514 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1516 lCount = AFSObjectInfoDecrement( pCurrentObject,
1517 AFS_OBJECT_REFERENCE_WORKER);
1519 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1520 AFS_TRACE_LEVEL_VERBOSE,
1521 "AFSExamineObjectInfo Decrement6 count on object %p Cnt %d\n",
1526 // The VolumeCB TreeLock is held exclusive so the
1527 // ObjectReferenceCount cannot change.
1530 AFSDeleteObjectInfo( &pCurrentObject);
1535 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1542 if ( pCurrentObject != NULL)
1545 lCount = AFSObjectInfoDecrement( pCurrentObject,
1546 AFS_OBJECT_REFERENCE_WORKER);
1548 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1549 AFS_TRACE_LEVEL_VERBOSE,
1550 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1558 // Called with VolumeCB->VolumeLock held shared.
1562 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1564 NTSTATUS ntStatus = STATUS_SUCCESS;
1565 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1566 BOOLEAN bReleaseVolumeTreeLock = FALSE;
1567 BOOLEAN bVolumeObject = FALSE;
1571 // The Volume ObjectInfoTree TreeLock must be held exclusive to
1572 // prevent other threads from obtaining a reference to an ObjectInfoCB
1573 // via AFSFindObjectInfo() while it is being deleted. This is
1574 // annoying but the alternative is to hold the TreeLock shared during
1575 // garbage collection and exclusive during find operations.
1578 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1582 bReleaseVolumeTreeLock = TRUE;
1584 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1586 lCount = AFSObjectInfoIncrement( pCurrentObject,
1587 AFS_OBJECT_REFERENCE_WORKER);
1589 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1590 AFS_TRACE_LEVEL_VERBOSE,
1591 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1597 while( pCurrentObject != NULL &&
1598 bReleaseVolumeTreeLock == TRUE)
1601 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1604 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1607 // If the end of the VolumeCB ObjectInfo List is reached, then
1608 // the next ObjectInformationCB to examine is the one embedded within
1609 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1611 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1612 // is being examined.
1615 if( pNextObject == NULL &&
1616 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1619 pNextObject = &pVolumeCB->ObjectInformation;
1622 bVolumeObject = FALSE;
1627 lCount = AFSObjectInfoIncrement( pNextObject,
1628 AFS_OBJECT_REFERENCE_WORKER);
1630 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1631 AFS_TRACE_LEVEL_VERBOSE,
1632 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1642 bVolumeObject = TRUE;
1645 AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeTreeLock);
1647 if ( bReleaseVolumeTreeLock == TRUE &&
1648 ( ExGetExclusiveWaiterCount( pVolumeCB->ObjectInfoTree.TreeLock) > 0 ||
1649 ExGetSharedWaiterCount( pVolumeCB->ObjectInfoTree.TreeLock) > 0))
1652 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1654 bReleaseVolumeTreeLock = FALSE;
1657 // The CurrentObject is either destroyed or the reference count has been
1658 // dropped by AFSExamineObjectInfo().
1661 if ( bReleaseVolumeTreeLock == FALSE)
1665 // Try to obtain the Volume's ObjectInfoTree.TreeLock after dropping
1666 // other locks and continue.
1669 bReleaseVolumeTreeLock = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1673 pCurrentObject = pNextObject;
1678 if ( pCurrentObject != NULL)
1681 lCount = AFSObjectInfoDecrement( pCurrentObject,
1682 AFS_OBJECT_REFERENCE_WORKER);
1684 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1685 AFS_TRACE_LEVEL_VERBOSE,
1686 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1691 if( bReleaseVolumeTreeLock)
1694 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1700 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1703 UNREFERENCED_PARAMETER(Context);
1704 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1705 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1706 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1707 LARGE_INTEGER DueTime;
1710 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1713 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1714 AFS_TRACE_LEVEL_VERBOSE,
1715 "AFSPrimaryVolumeWorkerThread Initialized\n"));
1718 // Initialize the timer for the worker thread
1721 DueTime.QuadPart = -(5000);
1725 KeInitializeTimerEx( &Timer,
1726 SynchronizationTimer);
1728 KeSetTimerEx( &Timer,
1734 // Indicate that we are initialized and ready
1737 KeSetEvent( &pPoolContext->WorkerThreadReady,
1742 // Indicate we are initialized
1745 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1747 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1750 KeWaitForSingleObject( &Timer,
1757 // This is the primary volume worker so it will traverse the volume list
1758 // looking for cleanup or volumes requiring private workers
1761 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1764 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1766 while( pVolumeCB != NULL)
1769 if( pVolumeCB == AFSGlobalRoot ||
1770 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1774 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1779 if( pVolumeCB->ObjectInfoListHead == NULL)
1782 AFSReleaseResource( pVolumeCB->VolumeLock);
1784 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1786 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1789 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1792 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1796 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1798 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1800 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1805 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1807 AFSAcquireExcl( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1811 // If VolumeCB is idle, the Volume can be garbage collected
1814 if( pVolumeCB->ObjectInfoListHead == NULL &&
1815 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1816 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1817 pVolumeCB->VolumeReferenceCount == 0 &&
1818 ( pVolumeCB->RootFcb == NULL ||
1819 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1820 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1823 AFSRemoveRootFcb( pVolumeCB);
1825 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1827 AFSRemoveVolume( pVolumeCB);
1832 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1834 AFSReleaseResource( pVolumeCB->VolumeLock);
1837 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1839 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1841 pVolumeCB = pNextVolume;
1847 // Don't need this lock anymore now that we have a volume cb to work with
1850 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1853 // For now we only need the volume lock shared
1856 AFSConvertToShared( pVolumeCB->VolumeLock);
1858 AFSExamineVolume( pVolumeCB);
1864 AFSReleaseResource( pVolumeCB->VolumeLock);
1866 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1869 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1872 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1874 } // worker thread loop
1876 KeCancelTimer( &Timer);
1878 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1880 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1881 AFS_TRACE_LEVEL_VERBOSE,
1882 "AFSPrimaryVolumeWorkerThread Exiting\n"));
1884 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1889 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1894 PsTerminateSystemThread( 0);
1900 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1903 NTSTATUS ntStatus = STATUS_SUCCESS;
1904 AFSDeviceExt *pControlDevExt = NULL;
1907 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1909 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1910 AFS_TRACE_LEVEL_VERBOSE,
1911 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1912 &pControlDevExt->Specific.Control.QueueLock,
1913 PsGetCurrentThread()));
1915 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1918 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1920 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1921 AFS_TRACE_LEVEL_VERBOSE,
1922 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1926 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1929 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1934 pControlDevExt->Specific.Control.QueueHead = WorkItem;
1937 WorkItem->next = NULL;
1938 pControlDevExt->Specific.Control.QueueTail = WorkItem;
1940 // indicate that the queue has nodes
1941 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
1945 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
1951 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1954 NTSTATUS ntStatus = STATUS_SUCCESS;
1955 AFSDeviceExt *pControlDevExt = NULL;
1958 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1960 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1961 AFS_TRACE_LEVEL_VERBOSE,
1962 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1963 &pControlDevExt->Specific.Control.IOQueueLock,
1964 PsGetCurrentThread()));
1966 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
1969 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
1971 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1972 AFS_TRACE_LEVEL_VERBOSE,
1973 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
1977 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
1980 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
1985 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
1988 WorkItem->next = NULL;
1989 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
1991 // indicate that the queue has nodes
1992 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
1996 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2002 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2005 NTSTATUS ntStatus = STATUS_SUCCESS;
2006 AFSDeviceExt *pControlDevExt = NULL;
2009 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2011 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2012 AFS_TRACE_LEVEL_VERBOSE,
2013 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2014 &pControlDevExt->Specific.Control.QueueLock,
2015 PsGetCurrentThread()));
2017 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2020 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2022 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2024 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2026 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2027 AFS_TRACE_LEVEL_VERBOSE,
2028 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2033 // indicate that the queue has nodes
2036 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2040 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2049 AFSWorkItem *pWorkItem = NULL;
2050 AFSDeviceExt *pControlDevExt = NULL;
2053 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2055 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2056 AFS_TRACE_LEVEL_VERBOSE,
2057 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2058 &pControlDevExt->Specific.Control.QueueLock,
2059 PsGetCurrentThread()));
2061 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2064 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2067 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2069 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2071 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2072 AFS_TRACE_LEVEL_VERBOSE,
2073 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2076 PsGetCurrentThreadId()));
2078 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2080 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2083 pControlDevExt->Specific.Control.QueueTail = NULL;
2089 // Wake up another worker
2092 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2098 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2104 AFSRemoveIOWorkItem()
2107 AFSWorkItem *pWorkItem = NULL;
2108 AFSDeviceExt *pControlDevExt = NULL;
2111 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2113 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2114 AFS_TRACE_LEVEL_VERBOSE,
2115 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2116 &pControlDevExt->Specific.Control.IOQueueLock,
2117 PsGetCurrentThread()));
2119 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2122 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2125 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2127 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2129 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2130 AFS_TRACE_LEVEL_VERBOSE,
2131 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2134 PsGetCurrentThreadId()));
2136 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2138 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2141 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2147 // Wake up another worker
2150 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2156 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2162 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2165 NTSTATUS ntStatus = STATUS_SUCCESS;
2166 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2169 // Submit the work item to the worker
2172 ntStatus = AFSInsertWorkitem( WorkItem);
2178 // Sync request so block on the work item event
2181 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2192 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2195 NTSTATUS ntStatus = STATUS_SUCCESS;
2196 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2199 // Submit the work item to the worker
2202 ntStatus = AFSInsertIOWorkitem( WorkItem);
2208 // Sync request so block on the work item event
2211 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2222 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2225 NTSTATUS ntStatus = STATUS_SUCCESS;
2226 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2229 // Submit the work item to the worker
2232 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2238 // Sync request so block on the work item event
2241 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2252 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2256 NTSTATUS ntStatus = STATUS_SUCCESS;
2257 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2258 AFSWorkItem *pWorkItem = NULL;
2264 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2265 AFS_TRACE_LEVEL_VERBOSE,
2266 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2267 Fcb->ObjectInformation->FileId.Cell,
2268 Fcb->ObjectInformation->FileId.Volume,
2269 Fcb->ObjectInformation->FileId.Vnode,
2270 Fcb->ObjectInformation->FileId.Unique));
2273 // Increment our flush count here just to keep the number of items in the
2274 // queue down. We'll decrement it just below.
2277 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2282 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2283 AFS_TRACE_LEVEL_VERBOSE,
2284 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2285 Fcb->ObjectInformation->FileId.Cell,
2286 Fcb->ObjectInformation->FileId.Volume,
2287 Fcb->ObjectInformation->FileId.Vnode,
2288 Fcb->ObjectInformation->FileId.Unique));
2290 try_return( ntStatus);
2293 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2296 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2297 AFS_TRACE_LEVEL_ERROR,
2298 "AFSQueueFlushExtents Failing request, in shutdown\n"));
2300 try_return( ntStatus = STATUS_TOO_LATE);
2304 // Allocate our request structure and send it to the worker
2307 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2308 sizeof( AFSWorkItem),
2311 if( pWorkItem == NULL)
2314 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2315 AFS_TRACE_LEVEL_ERROR,
2316 "AFSQueueFlushExtents Failed to allocate work item\n"));
2318 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2321 RtlZeroMemory( pWorkItem,
2322 sizeof( AFSWorkItem));
2324 pWorkItem->Size = sizeof( AFSWorkItem);
2326 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2328 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2330 if ( AuthGroup == NULL)
2333 RtlZeroMemory( &pWorkItem->AuthGroup,
2336 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2339 &pWorkItem->AuthGroup);
2343 RtlCopyMemory( &pWorkItem->AuthGroup,
2348 pWorkItem->Specific.Fcb.Fcb = Fcb;
2350 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2352 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2353 AFS_TRACE_LEVEL_VERBOSE,
2354 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2358 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2359 AFS_TRACE_LEVEL_VERBOSE,
2360 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2362 Fcb->ObjectInformation->FileId.Cell,
2363 Fcb->ObjectInformation->FileId.Volume,
2364 Fcb->ObjectInformation->FileId.Vnode,
2365 Fcb->ObjectInformation->FileId.Unique));
2367 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2371 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2372 AFS_TRACE_LEVEL_VERBOSE,
2373 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2374 Fcb->ObjectInformation->FileId.Cell,
2375 Fcb->ObjectInformation->FileId.Volume,
2376 Fcb->ObjectInformation->FileId.Vnode,
2377 Fcb->ObjectInformation->FileId.Unique,
2381 // Remove the count we added above
2384 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2386 ASSERT( lCount >= 0);
2391 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2396 if( !NT_SUCCESS( ntStatus))
2399 if( pWorkItem != NULL)
2402 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2404 AFSExFreePoolWithTag( pWorkItem,
2408 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2409 AFS_TRACE_LEVEL_ERROR,
2410 "AFSQueueFlushExtents Failed to queue request Status %08lX\n",
2414 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2419 "EXCEPTION - AFSQueueFlushExtents\n"));
2421 AFSDumpTraceFilesFnc();
2428 AFSQueueGlobalRootEnumeration()
2431 NTSTATUS ntStatus = STATUS_SUCCESS;
2432 AFSWorkItem *pWorkItem = NULL;
2437 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2438 sizeof(AFSWorkItem),
2440 if (NULL == pWorkItem)
2443 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2444 AFS_TRACE_LEVEL_ERROR,
2445 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n"));
2447 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2450 RtlZeroMemory( pWorkItem,
2451 sizeof(AFSWorkItem));
2453 pWorkItem->Size = sizeof( AFSWorkItem);
2455 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2457 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2458 AFS_TRACE_LEVEL_VERBOSE,
2459 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2462 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2466 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2467 AFS_TRACE_LEVEL_VERBOSE,
2468 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2471 if( !NT_SUCCESS( ntStatus))
2474 if( pWorkItem != NULL)
2477 AFSExFreePoolWithTag( pWorkItem,
2481 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2482 AFS_TRACE_LEVEL_ERROR,
2483 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2487 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2492 "EXCEPTION - AFSQueueGlobalRootEnumeration\n"));
2494 AFSDumpTraceFilesFnc();
2501 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2502 IN UCHAR FunctionCode,
2503 IN ULONG RequestFlags,
2504 IN AFSIoRun *IoRuns,
2506 IN AFSGatherIo *GatherIo)
2509 NTSTATUS ntStatus = STATUS_SUCCESS;
2510 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2511 AFSWorkItem *pWorkItem = NULL;
2516 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2519 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2520 AFS_TRACE_LEVEL_ERROR,
2521 "AFSQueueStartIos Failing request, in shutdown\n"));
2523 try_return( ntStatus = STATUS_TOO_LATE);
2527 // Allocate our request structure and send it to the worker
2530 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2531 sizeof( AFSWorkItem),
2534 if( pWorkItem == NULL)
2537 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2538 AFS_TRACE_LEVEL_ERROR,
2539 "AFSQueueStartIos Failed to allocate work item\n"));
2541 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2544 RtlZeroMemory( pWorkItem,
2545 sizeof( AFSWorkItem));
2547 KeInitializeEvent( &pWorkItem->Event,
2551 pWorkItem->Size = sizeof( AFSWorkItem);
2553 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2555 pWorkItem->RequestType = AFS_WORK_START_IOS;
2557 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2559 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2561 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2563 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2565 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2567 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2569 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2570 AFS_TRACE_LEVEL_VERBOSE,
2571 "AFSQueueStartIos Queuing IO Workitem %p\n",
2574 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2578 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2579 AFS_TRACE_LEVEL_VERBOSE,
2580 "AFSQueueStartIos Request complete Status %08lX\n",
2583 if( !NT_SUCCESS( ntStatus))
2586 if( pWorkItem != NULL)
2589 AFSExFreePoolWithTag( pWorkItem,
2594 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2599 "EXCEPTION - AFSQueueStartIos\n"));
2601 AFSDumpTraceFilesFnc();
2608 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2609 IN ULONG InvalidateReason)
2612 NTSTATUS ntStatus = STATUS_SUCCESS;
2613 AFSWorkItem *pWorkItem = NULL;
2618 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2619 sizeof(AFSWorkItem),
2621 if (NULL == pWorkItem)
2624 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2625 AFS_TRACE_LEVEL_ERROR,
2626 "AFSQueueInvalidateObject Failed to allocate work item\n"));
2628 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2631 RtlZeroMemory( pWorkItem,
2632 sizeof(AFSWorkItem));
2634 pWorkItem->Size = sizeof( AFSWorkItem);
2636 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2638 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2640 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2642 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2643 AFS_TRACE_LEVEL_VERBOSE,
2644 "AFSQueueInvalidateObject Workitem %p\n",
2647 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2651 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2652 AFS_TRACE_LEVEL_VERBOSE,
2653 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2656 if( !NT_SUCCESS( ntStatus))
2659 if( pWorkItem != NULL)
2662 AFSExFreePoolWithTag( pWorkItem,
2666 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2667 AFS_TRACE_LEVEL_ERROR,
2668 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2672 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2677 "EXCEPTION - AFSQueueInvalidateObject\n"));
2679 AFSDumpTraceFilesFnc();
2686 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2687 IN PFILE_OBJECT FileObject,
2688 IN HANDLE CallingUser,
2690 IN ULONG BytesToWrite,
2691 IN BOOLEAN bRetrying)
2693 NTSTATUS ntStatus = STATUS_SUCCESS;
2694 AFSWorkItem *pWorkItem = NULL;
2700 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2704 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2707 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2708 AFS_TRACE_LEVEL_ERROR,
2709 "%s Could not pin user memory item\n",
2712 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2715 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2716 sizeof(AFSWorkItem),
2719 if (NULL == pWorkItem)
2722 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2723 AFS_TRACE_LEVEL_ERROR,
2724 "%s Failed to allocate work item\n",
2727 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2730 RtlZeroMemory( pWorkItem,
2731 sizeof(AFSWorkItem));
2733 pWorkItem->Size = sizeof( AFSWorkItem);
2735 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2737 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2739 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2741 pWorkItem->Specific.AsynchIo.Irp = Irp;
2743 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2744 AFS_TRACE_LEVEL_VERBOSE,
2749 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2751 IoMarkIrpPending(Irp);
2753 ntStatus = STATUS_PENDING;
2755 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2760 "EXCEPTION - %s \n",
2763 ntStatus = GetExceptionCode();
2768 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2769 AFS_TRACE_LEVEL_VERBOSE,
2770 "%s complete Status %08lX\n",
2774 if( !NT_SUCCESS( ntStatus))
2777 if( pWorkItem != NULL)
2780 AFSExFreePoolWithTag( pWorkItem,
2784 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2785 AFS_TRACE_LEVEL_ERROR,
2786 "%s Failed to queue request Status %08lX\n",
2796 AFSPostedDeferredWrite( IN PVOID Context1,
2799 UNREFERENCED_PARAMETER( Context2);
2802 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2804 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2805 AFS_TRACE_LEVEL_ERROR,
2810 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2812 if (!NT_SUCCESS( ntStatus))
2815 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2817 AFSExFreePoolWithTag( pWorkItem,
2820 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2821 AFS_TRACE_LEVEL_ERROR,
2822 "%s (%p) Failed to queue request Status %08lX\n",
2824 pWorkItem->Specific.AsynchIo.Irp,