2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 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;
656 AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *) AFSRDRDeviceObject->DeviceExtension;
659 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
662 // Indicate that we are initialized and ready
665 KeSetEvent( &pPoolContext->WorkerThreadReady,
670 // Indicate we are initialized
673 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
675 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
681 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
684 if( !NT_SUCCESS( ntStatus))
687 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
688 AFS_TRACE_LEVEL_ERROR,
689 "AFSWorkerThread Wait for queue items failed Status %08lX\n",
692 ntStatus = STATUS_SUCCESS;
697 pWorkItem = AFSRemoveWorkItem();
699 if( pWorkItem == NULL)
702 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
711 freeWorkItem = !(pWorkItem->RequestFlags & AFS_SYNCHRONOUS_REQUEST);
714 // Switch on the type of work item to process
717 switch( pWorkItem->RequestType)
720 case AFS_WORK_FLUSH_FCB:
723 if( !BooleanFlagOn( pRDRDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO))
725 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
726 &pWorkItem->AuthGroup);
728 if( !NT_SUCCESS( ntStatus))
731 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
732 &pWorkItem->AuthGroup,
737 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
739 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
744 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
747 AFSEnumerateGlobalRoot( NULL);
752 case AFS_WORK_INVALIDATE_OBJECT:
755 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
756 pWorkItem->Specific.Invalidate.InvalidateReason);
761 case AFS_WORK_START_IOS:
767 case AFS_WORK_GET_AUTH_ID:
771 AFSPerformGetAuthId( pWorkItem->Specific.GetAuthId.peProcess,
772 pWorkItem->Specific.GetAuthId.peThread,
773 &pWorkItem->Specific.GetAuthId.AuthId);
780 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
781 AFS_TRACE_LEVEL_ERROR,
782 "AFSWorkerThread Unknown request type %d\n",
783 pWorkItem->RequestType));
791 AFSExFreePoolWithTag( pWorkItem,
797 KeSetEvent( &pWorkItem->Event,
802 ntStatus = STATUS_SUCCESS;
805 } // worker thread loop
807 // Wake up another worker so they too can exit
809 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
813 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
815 PsTerminateSystemThread( 0);
821 AFSIOWorkerThread( IN PVOID Context)
824 NTSTATUS ntStatus = STATUS_SUCCESS;
825 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
826 AFSWorkItem *pWorkItem;
827 BOOLEAN freeWorkItem = TRUE;
828 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
830 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
833 // Indicate that we are initialized and ready
836 KeSetEvent( &pPoolContext->WorkerThreadReady,
842 // Indicate we are initialized
845 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
847 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
853 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
856 if( !NT_SUCCESS( ntStatus))
859 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
860 AFS_TRACE_LEVEL_ERROR,
861 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n",
864 ntStatus = STATUS_SUCCESS;
869 pWorkItem = AFSRemoveIOWorkItem();
871 if( pWorkItem == NULL)
874 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
886 // Switch on the type of work item to process
889 switch( pWorkItem->RequestType)
892 case AFS_WORK_START_IOS:
895 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
898 // The final status is in the gather io
901 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
902 pWorkItem->Specific.CacheAccess.FunctionCode,
903 pWorkItem->Specific.CacheAccess.RequestFlags,
904 pWorkItem->Specific.CacheAccess.IoRuns,
905 pWorkItem->Specific.CacheAccess.RunCount,
906 pWorkItem->Specific.CacheAccess.GatherIo);
909 // Regardless of the status we we do the complete - there may
911 // Decrement the count - setting the event if we were told
912 // to. This may trigger completion.
915 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
922 case AFS_WORK_DEFERRED_WRITE:
925 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
926 pWorkItem->Specific.AsynchIo.Irp,
927 pWorkItem->Specific.AsynchIo.CallingProcess,
937 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
938 AFS_TRACE_LEVEL_ERROR,
939 "AFSIOWorkerThread Unknown request type %d\n",
940 pWorkItem->RequestType));
948 AFSLibExFreePoolWithTag( pWorkItem,
952 ntStatus = STATUS_SUCCESS;
955 } // worker thread loop
957 // Wake up another IOWorker so they too can exit
959 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
963 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
965 PsTerminateSystemThread( 0);
971 // Called with VolumeCB->ObjectInfoTree.TreeLock held exclusive.
972 // pCurrentObject->ObjectReferenceCount is incremented by the caller.
974 // The *pbReleaseVolumeLock is set to FALSE if the TreeLock is dropped
977 // pCurrentObject must either be destroyed or the reference count
978 // decremented before returning.
982 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
983 IN BOOLEAN bVolumeObject,
984 IN OUT BOOLEAN * pbReleaseVolumeLock)
986 NTSTATUS ntStatus = STATUS_SUCCESS;
987 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
988 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
989 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
990 AFSObjectInfoCB *pCurrentChildObject = NULL;
991 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
992 LARGE_INTEGER liCurrentTime;
999 ASSERT( ExIsResourceAcquiredExclusiveLite( pVolumeCB->ObjectInfoTree.TreeLock));
1001 switch ( pCurrentObject->FileType)
1004 case AFS_FILE_TYPE_DIRECTORY:
1007 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1010 try_return( ntStatus);
1014 // If this object is deleted then remove it from the parent, if we can
1017 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED))
1020 if ( pCurrentObject->ObjectReferenceCount == 1 &&
1021 ( pCurrentObject->Fcb == NULL ||
1022 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1023 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1024 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1027 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1030 if ( pCurrentObject->Fcb != NULL)
1033 AFSRemoveFcb( &pCurrentObject->Fcb);
1036 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1039 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1042 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1044 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1046 lCount = AFSObjectInfoDecrement( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1047 AFS_OBJECT_REFERENCE_PIOCTL);
1049 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1050 AFS_TRACE_LEVEL_VERBOSE,
1051 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1052 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1055 ASSERT( lCount == 0);
1060 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1063 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1065 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged,
1066 AFS_DIR_ENTRY_NP_TAG);
1068 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1069 AFS_TRACE_LEVEL_VERBOSE,
1070 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1071 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB));
1073 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB,
1076 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB = NULL;
1079 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1081 lCount = AFSObjectInfoDecrement( pCurrentObject,
1082 AFS_OBJECT_REFERENCE_WORKER);
1084 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1085 AFS_TRACE_LEVEL_VERBOSE,
1086 "AFSExamineObjectInfo Decrement1 count on object %p Cnt %d\n",
1090 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1091 AFS_TRACE_LEVEL_VERBOSE,
1092 "AFSExamineObjectInfo Deleting deleted object %p\n",
1096 // The CurrentReferenceCount must be zero or we would not
1097 // have gotten this far. It is safe to delete the ObjectInfoCB.
1100 AFSDeleteObjectInfo( &pCurrentObject);
1104 // Finished processing the AFS_OBJECT_FLAGS_DELETED case.
1107 try_return( ntStatus);
1111 // pCurrentObject not marked Deleted.
1114 if ( pCurrentObject->Fcb != NULL &&
1115 pCurrentObject->Fcb->CcbListHead != NULL)
1118 try_return( ntStatus);
1121 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1122 ( pCurrentObject->Fcb != NULL &&
1123 pCurrentObject->Fcb->OpenReferenceCount > 0))
1126 try_return( ntStatus);
1129 if ( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1130 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1134 // Directory Entry Processing
1136 // First pass is performed with the TreeLock held shared.
1137 // If we detect any objects in use, we give up quickly without
1138 // making any changes and without blocking other threads.
1139 // The second pass is performed with the TreeLock held exclusive
1140 // so deletions can take place.
1143 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1147 try_return( ntStatus);
1150 KeQueryTickCount( &liCurrentTime);
1152 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1154 while( pCurrentDirEntry != NULL)
1157 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1158 pCurrentDirEntry->NameArrayReferenceCount > 0)
1161 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1163 try_return( ntStatus);
1166 if ( pCurrentDirEntry->ObjectInformation != NULL)
1169 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1170 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1173 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1175 try_return( ntStatus);
1178 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1179 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1180 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1183 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1185 try_return( ntStatus);
1188 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1191 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1197 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1204 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1207 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1208 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1216 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1219 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1221 if( pCurrentDirEntry != NULL)
1224 try_return( ntStatus);
1228 // Attempt the second pass with the TreeLock held exclusive.
1229 // The the TreeLock cannot be obtained without blocking it means that
1230 // the directory is in active use, so do nothing.
1233 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1237 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1240 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1242 try_return( ntStatus);
1245 KeQueryTickCount( &liCurrentTime);
1247 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1249 while( pCurrentDirEntry != NULL)
1252 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1258 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1264 if ( pCurrentDirEntry->ObjectInformation != NULL)
1267 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1268 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1274 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1275 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1276 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1282 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1285 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1291 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1298 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1301 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1302 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1310 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1313 if( pCurrentDirEntry != NULL)
1317 // At least one entry in the directory is actively in use.
1318 // Drop the lock and exit without removing anything.
1321 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1323 try_return( ntStatus);
1327 // Third pass, process each directory entry and remove what we can.
1328 // The VolumeCB TreeLock and the ObjectInfo TreeLock are still held exclusive.
1331 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1333 while( pCurrentDirEntry != NULL)
1336 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1339 // Delete the DirectoryCB which in turn removes the DIRENTRY reference
1340 // count from the associated ObjectInfoCB. The reference count held above
1341 // may now be the only one left.
1344 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1345 AFS_TRACE_LEVEL_VERBOSE,
1346 "AFSExamineObjectInfo Deleting DE %wZ Object %p\n",
1347 &pCurrentDirEntry->NameInformation.FileName,
1348 pCurrentDirEntry->ObjectInformation));
1350 AFSDeleteDirEntry( pCurrentObject,
1353 pCurrentDirEntry = pNextDirEntry;
1357 // Clear our enumerated flag on this object so we retrieve info again on next access
1360 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1362 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1365 else if ( bVolumeObject == FALSE)
1371 if( pCurrentObject->ObjectReferenceCount > 1 ||
1372 pCurrentObject->Fcb != NULL &&
1373 pCurrentObject->Fcb->OpenReferenceCount > 0)
1376 try_return( ntStatus);
1379 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1382 KeQueryTickCount( &liCurrentTime);
1384 if( pCurrentObject->ObjectReferenceCount == 1 &&
1385 ( pCurrentObject->Fcb == NULL ||
1386 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1387 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1388 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1389 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1392 AFSRemoveFcb( &pCurrentObject->Fcb);
1394 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1396 lCount = AFSObjectInfoDecrement( pCurrentObject,
1397 AFS_OBJECT_REFERENCE_WORKER);
1399 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1400 AFS_TRACE_LEVEL_VERBOSE,
1401 "AFSExamineObjectInfo Decrement4 count on object %p Cnt %d\n",
1406 // The Volume TreeLock is held exclusive. Therefore, the ObjectReferenceCount
1407 // cannot change. It is therefore safe to delete the ObjectInfoCB
1410 AFSDeleteObjectInfo( &pCurrentObject);
1415 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1422 case AFS_FILE_TYPE_FILE:
1425 if( pCurrentObject->ObjectReferenceCount > 1 ||
1426 pCurrentObject->Fcb != NULL &&
1427 pCurrentObject->Fcb->OpenReferenceCount > 0)
1430 try_return( ntStatus);
1433 if( pCurrentObject->Fcb != NULL)
1436 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1439 // Dropping the VolumeCB TreeLock permits the
1440 // pCurrentObject->ObjectReferenceCount to change.
1441 // But it cannot be held across the AFSCleanupFcb
1445 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1448 if (!AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1452 *pbReleaseVolumeLock = FALSE;
1455 if ( ntStatus == STATUS_RETRY ||
1456 *pbReleaseVolumeLock == FALSE)
1460 // The Fcb is in use.
1463 try_return( ntStatus);
1468 // VolumeCB is held exclusive
1471 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1474 KeQueryTickCount( &liCurrentTime);
1476 if( pCurrentObject->ObjectReferenceCount == 1 &&
1477 ( pCurrentObject->Fcb == NULL ||
1478 ( pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1479 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount == 0)) &&
1480 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1481 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1482 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1485 AFSRemoveFcb( &pCurrentObject->Fcb);
1487 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1489 lCount = AFSObjectInfoDecrement( pCurrentObject,
1490 AFS_OBJECT_REFERENCE_WORKER);
1492 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1493 AFS_TRACE_LEVEL_VERBOSE,
1494 "AFSExamineObjectInfo Decrement5 count on object %p Cnt %d\n",
1499 // The VolumeCB TreeLock is held exclusive so the
1500 // ObjectReferenceCount cannot change.
1503 AFSDeleteObjectInfo( &pCurrentObject);
1508 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1517 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1520 KeQueryTickCount( &liCurrentTime);
1522 if( pCurrentObject->ObjectReferenceCount == 1 &&
1523 ( pCurrentObject->Fcb == NULL ||
1524 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1525 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1526 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1527 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1530 AFSRemoveFcb( &pCurrentObject->Fcb);
1532 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1534 lCount = AFSObjectInfoDecrement( pCurrentObject,
1535 AFS_OBJECT_REFERENCE_WORKER);
1537 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1538 AFS_TRACE_LEVEL_VERBOSE,
1539 "AFSExamineObjectInfo Decrement6 count on object %p Cnt %d\n",
1544 // The VolumeCB TreeLock is held exclusive so the
1545 // ObjectReferenceCount cannot change.
1548 AFSDeleteObjectInfo( &pCurrentObject);
1553 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1560 if ( pCurrentObject != NULL)
1563 lCount = AFSObjectInfoDecrement( pCurrentObject,
1564 AFS_OBJECT_REFERENCE_WORKER);
1566 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1567 AFS_TRACE_LEVEL_VERBOSE,
1568 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1576 // Called with VolumeCB->VolumeLock held shared.
1580 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1582 NTSTATUS ntStatus = STATUS_SUCCESS;
1583 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1584 BOOLEAN bReleaseVolumeTreeLock = FALSE;
1585 BOOLEAN bVolumeObject = FALSE;
1589 // The Volume ObjectInfoTree TreeLock must be held exclusive to
1590 // prevent other threads from obtaining a reference to an ObjectInfoCB
1591 // via AFSFindObjectInfo() while it is being deleted. This is
1592 // annoying but the alternative is to hold the TreeLock shared during
1593 // garbage collection and exclusive during find operations.
1596 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1600 bReleaseVolumeTreeLock = TRUE;
1602 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1604 lCount = AFSObjectInfoIncrement( pCurrentObject,
1605 AFS_OBJECT_REFERENCE_WORKER);
1607 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1608 AFS_TRACE_LEVEL_VERBOSE,
1609 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1615 while( pCurrentObject != NULL &&
1616 bReleaseVolumeTreeLock == TRUE)
1619 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1622 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1625 // If the end of the VolumeCB ObjectInfo List is reached, then
1626 // the next ObjectInformationCB to examine is the one embedded within
1627 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1629 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1630 // is being examined.
1633 if( pNextObject == NULL &&
1634 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1637 pNextObject = &pVolumeCB->ObjectInformation;
1640 bVolumeObject = FALSE;
1645 lCount = AFSObjectInfoIncrement( pNextObject,
1646 AFS_OBJECT_REFERENCE_WORKER);
1648 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1649 AFS_TRACE_LEVEL_VERBOSE,
1650 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1660 bVolumeObject = TRUE;
1663 AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeTreeLock);
1665 if ( bReleaseVolumeTreeLock == TRUE &&
1666 ( ExGetExclusiveWaiterCount( pVolumeCB->ObjectInfoTree.TreeLock) > 0 ||
1667 ExGetSharedWaiterCount( pVolumeCB->ObjectInfoTree.TreeLock) > 0))
1670 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1672 bReleaseVolumeTreeLock = FALSE;
1675 // The CurrentObject is either destroyed or the reference count has been
1676 // dropped by AFSExamineObjectInfo().
1679 if ( bReleaseVolumeTreeLock == FALSE)
1683 // Try to obtain the Volume's ObjectInfoTree.TreeLock after dropping
1684 // other locks and continue.
1687 bReleaseVolumeTreeLock = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1691 pCurrentObject = pNextObject;
1696 if ( pCurrentObject != NULL)
1699 lCount = AFSObjectInfoDecrement( pCurrentObject,
1700 AFS_OBJECT_REFERENCE_WORKER);
1702 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1703 AFS_TRACE_LEVEL_VERBOSE,
1704 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1709 if( bReleaseVolumeTreeLock)
1712 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1718 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1721 UNREFERENCED_PARAMETER(Context);
1722 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1723 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1724 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1725 LARGE_INTEGER DueTime;
1728 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1731 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1732 AFS_TRACE_LEVEL_VERBOSE,
1733 "AFSPrimaryVolumeWorkerThread Initialized\n"));
1736 // Initialize the timer for the worker thread
1739 DueTime.QuadPart = -(5000);
1743 KeInitializeTimerEx( &Timer,
1744 SynchronizationTimer);
1746 KeSetTimerEx( &Timer,
1752 // Indicate that we are initialized and ready
1755 KeSetEvent( &pPoolContext->WorkerThreadReady,
1760 // Indicate we are initialized
1763 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1765 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1768 KeWaitForSingleObject( &Timer,
1775 // This is the primary volume worker so it will traverse the volume list
1776 // looking for cleanup or volumes requiring private workers
1779 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1782 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1784 while( pVolumeCB != NULL)
1787 if( pVolumeCB == AFSGlobalRoot ||
1788 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1792 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1797 if( pVolumeCB->ObjectInfoListHead == NULL)
1800 AFSReleaseResource( pVolumeCB->VolumeLock);
1802 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1804 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1807 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1810 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1814 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1816 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1818 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1823 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1825 AFSAcquireExcl( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1829 // If VolumeCB is idle, the Volume can be garbage collected
1832 if( pVolumeCB->ObjectInfoListHead == NULL &&
1833 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1834 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1835 pVolumeCB->VolumeReferenceCount == 0 &&
1836 ( pVolumeCB->RootFcb == NULL ||
1837 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1838 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1841 AFSRemoveRootFcb( pVolumeCB);
1843 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1845 AFSRemoveVolume( pVolumeCB);
1850 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1852 AFSReleaseResource( pVolumeCB->VolumeLock);
1855 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1857 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1859 pVolumeCB = pNextVolume;
1865 // Don't need this lock anymore now that we have a volume cb to work with
1868 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1871 // For now we only need the volume lock shared
1874 AFSConvertToShared( pVolumeCB->VolumeLock);
1876 AFSExamineVolume( pVolumeCB);
1882 AFSReleaseResource( pVolumeCB->VolumeLock);
1884 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1887 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1890 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1892 } // worker thread loop
1894 KeCancelTimer( &Timer);
1896 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1898 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1899 AFS_TRACE_LEVEL_VERBOSE,
1900 "AFSPrimaryVolumeWorkerThread Exiting\n"));
1902 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1907 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1912 PsTerminateSystemThread( 0);
1918 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1921 NTSTATUS ntStatus = STATUS_SUCCESS;
1922 AFSDeviceExt *pControlDevExt = NULL;
1925 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1927 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1928 AFS_TRACE_LEVEL_VERBOSE,
1929 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1930 &pControlDevExt->Specific.Control.QueueLock,
1931 PsGetCurrentThread()));
1933 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1936 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1938 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1939 AFS_TRACE_LEVEL_VERBOSE,
1940 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1944 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1947 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1952 pControlDevExt->Specific.Control.QueueHead = WorkItem;
1955 WorkItem->next = NULL;
1956 pControlDevExt->Specific.Control.QueueTail = WorkItem;
1958 // indicate that the queue has nodes
1959 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
1963 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
1969 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1972 NTSTATUS ntStatus = STATUS_SUCCESS;
1973 AFSDeviceExt *pControlDevExt = NULL;
1976 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1978 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1979 AFS_TRACE_LEVEL_VERBOSE,
1980 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1981 &pControlDevExt->Specific.Control.IOQueueLock,
1982 PsGetCurrentThread()));
1984 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
1987 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
1989 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1990 AFS_TRACE_LEVEL_VERBOSE,
1991 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
1995 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
1998 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
2003 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
2006 WorkItem->next = NULL;
2007 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
2009 // indicate that the queue has nodes
2010 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2014 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2020 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2023 NTSTATUS ntStatus = STATUS_SUCCESS;
2024 AFSDeviceExt *pControlDevExt = NULL;
2027 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2029 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2030 AFS_TRACE_LEVEL_VERBOSE,
2031 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2032 &pControlDevExt->Specific.Control.QueueLock,
2033 PsGetCurrentThread()));
2035 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2038 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2040 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2042 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2044 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2045 AFS_TRACE_LEVEL_VERBOSE,
2046 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2051 // indicate that the queue has nodes
2054 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2058 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2067 AFSWorkItem *pWorkItem = NULL;
2068 AFSDeviceExt *pControlDevExt = NULL;
2071 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2073 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2074 AFS_TRACE_LEVEL_VERBOSE,
2075 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2076 &pControlDevExt->Specific.Control.QueueLock,
2077 PsGetCurrentThread()));
2079 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2082 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2085 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2087 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2089 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2090 AFS_TRACE_LEVEL_VERBOSE,
2091 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2094 PsGetCurrentThreadId()));
2096 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2098 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2101 pControlDevExt->Specific.Control.QueueTail = NULL;
2107 // Wake up another worker
2110 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2116 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2122 AFSRemoveIOWorkItem()
2125 AFSWorkItem *pWorkItem = NULL;
2126 AFSDeviceExt *pControlDevExt = NULL;
2129 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2131 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2132 AFS_TRACE_LEVEL_VERBOSE,
2133 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2134 &pControlDevExt->Specific.Control.IOQueueLock,
2135 PsGetCurrentThread()));
2137 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2140 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2143 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2145 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2147 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2148 AFS_TRACE_LEVEL_VERBOSE,
2149 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2152 PsGetCurrentThreadId()));
2154 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2156 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2159 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2165 // Wake up another worker
2168 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2174 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2180 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2183 NTSTATUS ntStatus = STATUS_SUCCESS;
2184 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2187 // Submit the work item to the worker
2190 ntStatus = AFSInsertWorkitem( WorkItem);
2196 // Sync request so block on the work item event
2199 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2210 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2213 NTSTATUS ntStatus = STATUS_SUCCESS;
2214 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2217 // Submit the work item to the worker
2220 ntStatus = AFSInsertIOWorkitem( WorkItem);
2226 // Sync request so block on the work item event
2229 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2240 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2243 NTSTATUS ntStatus = STATUS_SUCCESS;
2244 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2247 // Submit the work item to the worker
2250 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2256 // Sync request so block on the work item event
2259 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2270 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2274 NTSTATUS ntStatus = STATUS_SUCCESS;
2275 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2276 AFSWorkItem *pWorkItem = NULL;
2282 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2283 AFS_TRACE_LEVEL_VERBOSE,
2284 "AFSQueueFlushExtents Queuing request 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));
2291 // Increment our flush count here just to keep the number of items in the
2292 // queue down. We'll decrement it just below.
2295 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2300 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2301 AFS_TRACE_LEVEL_VERBOSE,
2302 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2303 Fcb->ObjectInformation->FileId.Cell,
2304 Fcb->ObjectInformation->FileId.Volume,
2305 Fcb->ObjectInformation->FileId.Vnode,
2306 Fcb->ObjectInformation->FileId.Unique));
2308 try_return( ntStatus);
2311 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2314 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2315 AFS_TRACE_LEVEL_ERROR,
2316 "AFSQueueFlushExtents Failing request, in shutdown\n"));
2318 try_return( ntStatus = STATUS_TOO_LATE);
2322 // Allocate our request structure and send it to the worker
2325 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2326 sizeof( AFSWorkItem),
2329 if( pWorkItem == NULL)
2332 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2333 AFS_TRACE_LEVEL_ERROR,
2334 "AFSQueueFlushExtents Failed to allocate work item\n"));
2336 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2339 RtlZeroMemory( pWorkItem,
2340 sizeof( AFSWorkItem));
2342 pWorkItem->Size = sizeof( AFSWorkItem);
2344 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2346 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2348 if ( AuthGroup == NULL)
2351 RtlZeroMemory( &pWorkItem->AuthGroup,
2354 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2357 &pWorkItem->AuthGroup);
2361 RtlCopyMemory( &pWorkItem->AuthGroup,
2366 pWorkItem->Specific.Fcb.Fcb = Fcb;
2368 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2370 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2371 AFS_TRACE_LEVEL_VERBOSE,
2372 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2376 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2377 AFS_TRACE_LEVEL_VERBOSE,
2378 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2380 Fcb->ObjectInformation->FileId.Cell,
2381 Fcb->ObjectInformation->FileId.Volume,
2382 Fcb->ObjectInformation->FileId.Vnode,
2383 Fcb->ObjectInformation->FileId.Unique));
2385 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2389 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2390 AFS_TRACE_LEVEL_VERBOSE,
2391 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2392 Fcb->ObjectInformation->FileId.Cell,
2393 Fcb->ObjectInformation->FileId.Volume,
2394 Fcb->ObjectInformation->FileId.Vnode,
2395 Fcb->ObjectInformation->FileId.Unique,
2399 // Remove the count we added above
2402 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2404 ASSERT( lCount >= 0);
2409 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2414 if( !NT_SUCCESS( ntStatus))
2417 if( pWorkItem != NULL)
2420 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2422 AFSExFreePoolWithTag( pWorkItem,
2426 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2427 AFS_TRACE_LEVEL_ERROR,
2428 "AFSQueueFlushExtents Failed to queue request Status %08lX\n",
2432 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2437 "EXCEPTION - AFSQueueFlushExtents\n"));
2439 AFSDumpTraceFilesFnc();
2446 AFSQueueGlobalRootEnumeration()
2449 NTSTATUS ntStatus = STATUS_SUCCESS;
2450 AFSWorkItem *pWorkItem = NULL;
2455 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2456 sizeof(AFSWorkItem),
2458 if (NULL == pWorkItem)
2461 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2462 AFS_TRACE_LEVEL_ERROR,
2463 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n"));
2465 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2468 RtlZeroMemory( pWorkItem,
2469 sizeof(AFSWorkItem));
2471 pWorkItem->Size = sizeof( AFSWorkItem);
2473 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2475 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2476 AFS_TRACE_LEVEL_VERBOSE,
2477 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2480 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2484 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2485 AFS_TRACE_LEVEL_VERBOSE,
2486 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2489 if( !NT_SUCCESS( ntStatus))
2492 if( pWorkItem != NULL)
2495 AFSExFreePoolWithTag( pWorkItem,
2499 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2500 AFS_TRACE_LEVEL_ERROR,
2501 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2505 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2510 "EXCEPTION - AFSQueueGlobalRootEnumeration\n"));
2512 AFSDumpTraceFilesFnc();
2519 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2520 IN UCHAR FunctionCode,
2521 IN ULONG RequestFlags,
2522 IN AFSIoRun *IoRuns,
2524 IN AFSGatherIo *GatherIo)
2527 NTSTATUS ntStatus = STATUS_SUCCESS;
2528 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2529 AFSWorkItem *pWorkItem = NULL;
2534 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2537 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2538 AFS_TRACE_LEVEL_ERROR,
2539 "AFSQueueStartIos Failing request, in shutdown\n"));
2541 try_return( ntStatus = STATUS_TOO_LATE);
2545 // Allocate our request structure and send it to the worker
2548 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2549 sizeof( AFSWorkItem),
2552 if( pWorkItem == NULL)
2555 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2556 AFS_TRACE_LEVEL_ERROR,
2557 "AFSQueueStartIos Failed to allocate work item\n"));
2559 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2562 RtlZeroMemory( pWorkItem,
2563 sizeof( AFSWorkItem));
2565 KeInitializeEvent( &pWorkItem->Event,
2569 pWorkItem->Size = sizeof( AFSWorkItem);
2571 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2573 pWorkItem->RequestType = AFS_WORK_START_IOS;
2575 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2577 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2579 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2581 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2583 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2585 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2587 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2588 AFS_TRACE_LEVEL_VERBOSE,
2589 "AFSQueueStartIos Queuing IO Workitem %p\n",
2592 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2596 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2597 AFS_TRACE_LEVEL_VERBOSE,
2598 "AFSQueueStartIos Request complete Status %08lX\n",
2601 if( !NT_SUCCESS( ntStatus))
2604 if( pWorkItem != NULL)
2607 AFSExFreePoolWithTag( pWorkItem,
2612 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2617 "EXCEPTION - AFSQueueStartIos\n"));
2619 AFSDumpTraceFilesFnc();
2626 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2627 IN ULONG InvalidateReason)
2630 NTSTATUS ntStatus = STATUS_SUCCESS;
2631 AFSWorkItem *pWorkItem = NULL;
2636 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2637 sizeof(AFSWorkItem),
2639 if (NULL == pWorkItem)
2642 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2643 AFS_TRACE_LEVEL_ERROR,
2644 "AFSQueueInvalidateObject Failed to allocate work item\n"));
2646 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2649 RtlZeroMemory( pWorkItem,
2650 sizeof(AFSWorkItem));
2652 pWorkItem->Size = sizeof( AFSWorkItem);
2654 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2656 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2658 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2660 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2661 AFS_TRACE_LEVEL_VERBOSE,
2662 "AFSQueueInvalidateObject Workitem %p\n",
2665 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2669 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2670 AFS_TRACE_LEVEL_VERBOSE,
2671 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2674 if( !NT_SUCCESS( ntStatus))
2677 if( pWorkItem != NULL)
2680 AFSExFreePoolWithTag( pWorkItem,
2684 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2685 AFS_TRACE_LEVEL_ERROR,
2686 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2690 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2695 "EXCEPTION - AFSQueueInvalidateObject\n"));
2697 AFSDumpTraceFilesFnc();
2704 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2705 IN PFILE_OBJECT FileObject,
2706 IN HANDLE CallingUser,
2708 IN ULONG BytesToWrite,
2709 IN BOOLEAN bRetrying)
2711 NTSTATUS ntStatus = STATUS_SUCCESS;
2712 AFSWorkItem *pWorkItem = NULL;
2718 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2722 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2725 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2726 AFS_TRACE_LEVEL_ERROR,
2727 "%s Could not pin user memory item\n",
2730 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2733 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2734 sizeof(AFSWorkItem),
2737 if (NULL == pWorkItem)
2740 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2741 AFS_TRACE_LEVEL_ERROR,
2742 "%s Failed to allocate work item\n",
2745 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2748 RtlZeroMemory( pWorkItem,
2749 sizeof(AFSWorkItem));
2751 pWorkItem->Size = sizeof( AFSWorkItem);
2753 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2755 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2757 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2759 pWorkItem->Specific.AsynchIo.Irp = Irp;
2761 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2762 AFS_TRACE_LEVEL_VERBOSE,
2767 IoMarkIrpPending(Irp);
2769 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2771 ntStatus = STATUS_PENDING;
2773 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2778 "EXCEPTION - %s \n",
2781 ntStatus = GetExceptionCode();
2786 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2787 AFS_TRACE_LEVEL_VERBOSE,
2788 "%s complete Status %08lX\n",
2792 if( !NT_SUCCESS( ntStatus))
2795 if( pWorkItem != NULL)
2798 AFSExFreePoolWithTag( pWorkItem,
2802 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2803 AFS_TRACE_LEVEL_ERROR,
2804 "%s Failed to queue request Status %08lX\n",
2814 AFSPostedDeferredWrite( IN PVOID Context1,
2817 UNREFERENCED_PARAMETER( Context2);
2820 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2822 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2823 AFS_TRACE_LEVEL_ERROR,
2828 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2830 if (!NT_SUCCESS( ntStatus))
2833 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2835 AFSExFreePoolWithTag( pWorkItem,
2838 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2839 AFS_TRACE_LEVEL_ERROR,
2840 "%s (%p) Failed to queue request Status %08lX\n",
2842 pWorkItem->Specific.AsynchIo.Irp,