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;
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,
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);
763 case AFS_WORK_START_IOS:
773 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
774 AFS_TRACE_LEVEL_ERROR,
775 "AFSWorkerThread Unknown request type %d\n",
776 pWorkItem->RequestType));
784 AFSExFreePoolWithTag( pWorkItem,
788 ntStatus = STATUS_SUCCESS;
791 } // worker thread loop
793 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
795 // Wake up another worker so they too can exit
797 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
801 PsTerminateSystemThread( 0);
807 AFSIOWorkerThread( IN PVOID Context)
810 NTSTATUS ntStatus = STATUS_SUCCESS;
811 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
812 AFSWorkItem *pWorkItem;
813 BOOLEAN freeWorkItem = TRUE;
814 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
816 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
819 // Indicate that we are initialized and ready
822 KeSetEvent( &pPoolContext->WorkerThreadReady,
828 // Indicate we are initialized
831 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
833 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
839 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
842 if( !NT_SUCCESS( ntStatus))
845 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
846 AFS_TRACE_LEVEL_ERROR,
847 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n",
850 ntStatus = STATUS_SUCCESS;
855 pWorkItem = AFSRemoveIOWorkItem();
857 if( pWorkItem == NULL)
860 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
872 // Switch on the type of work item to process
875 switch( pWorkItem->RequestType)
878 case AFS_WORK_START_IOS:
881 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
884 // The final status is in the gather io
887 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
888 pWorkItem->Specific.CacheAccess.FunctionCode,
889 pWorkItem->Specific.CacheAccess.RequestFlags,
890 pWorkItem->Specific.CacheAccess.IoRuns,
891 pWorkItem->Specific.CacheAccess.RunCount,
892 pWorkItem->Specific.CacheAccess.GatherIo);
895 // Regardless of the status we we do the complete - there may
897 // Decrement the count - setting the event if we were told
898 // to. This may trigger completion.
901 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
908 case AFS_WORK_DEFERRED_WRITE:
911 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
912 pWorkItem->Specific.AsynchIo.Irp,
913 pWorkItem->Specific.AsynchIo.CallingProcess,
923 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
924 AFS_TRACE_LEVEL_ERROR,
925 "AFSIOWorkerThread Unknown request type %d\n",
926 pWorkItem->RequestType));
934 AFSLibExFreePoolWithTag( pWorkItem,
938 ntStatus = STATUS_SUCCESS;
941 } // worker thread loop
943 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
945 // Wake up another IOWorker so they too can exit
947 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
951 PsTerminateSystemThread( 0);
957 // Called with VolumeCB->ObjectInfoTree.TreeLock held exclusive.
958 // pCurrentObject->ObjectReferenceCount is incremented by the caller.
960 // The *pbReleaseVolumeLock is set to FALSE if the TreeLock is dropped
963 // pCurrentObject must either be destroyed or the reference count
964 // decremented before returning.
968 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
969 IN BOOLEAN bVolumeObject,
970 IN OUT BOOLEAN * pbReleaseVolumeLock)
972 NTSTATUS ntStatus = STATUS_SUCCESS;
973 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
974 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
975 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
976 AFSObjectInfoCB *pCurrentChildObject = NULL;
977 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
978 LARGE_INTEGER liCurrentTime;
985 ASSERT( ExIsResourceAcquiredExclusiveLite( pVolumeCB->ObjectInfoTree.TreeLock));
987 switch ( pCurrentObject->FileType)
990 case AFS_FILE_TYPE_DIRECTORY:
993 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
996 try_return( ntStatus);
1000 // If this object is deleted then remove it from the parent, if we can
1003 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED))
1006 if ( pCurrentObject->ObjectReferenceCount == 1 &&
1007 ( pCurrentObject->Fcb == NULL ||
1008 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1009 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1010 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1013 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1016 if ( pCurrentObject->Fcb != NULL)
1019 AFSRemoveFcb( &pCurrentObject->Fcb);
1022 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1025 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1028 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1030 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1032 lCount = AFSObjectInfoDecrement( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1033 AFS_OBJECT_REFERENCE_PIOCTL);
1035 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1036 AFS_TRACE_LEVEL_VERBOSE,
1037 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1038 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1041 ASSERT( lCount == 0);
1046 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1049 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1051 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged,
1052 AFS_DIR_ENTRY_NP_TAG);
1054 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1055 AFS_TRACE_LEVEL_VERBOSE,
1056 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1057 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB));
1059 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB,
1062 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB = NULL;
1065 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1067 lCount = AFSObjectInfoDecrement( pCurrentObject,
1068 AFS_OBJECT_REFERENCE_WORKER);
1070 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1071 AFS_TRACE_LEVEL_VERBOSE,
1072 "AFSExamineObjectInfo Decrement1 count on object %p Cnt %d\n",
1076 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1077 AFS_TRACE_LEVEL_VERBOSE,
1078 "AFSExamineObjectInfo Deleting deleted object %p\n",
1082 // The CurrentReferenceCount must be zero or we would not
1083 // have gotten this far. It is safe to delete the ObjectInfoCB.
1086 AFSDeleteObjectInfo( &pCurrentObject);
1090 // Finished processing the AFS_OBJECT_FLAGS_DELETED case.
1093 try_return( ntStatus);
1097 // pCurrentObject not marked Deleted.
1100 if ( pCurrentObject->Fcb != NULL &&
1101 pCurrentObject->Fcb->CcbListHead != NULL)
1104 try_return( ntStatus);
1107 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1108 ( pCurrentObject->Fcb != NULL &&
1109 pCurrentObject->Fcb->OpenReferenceCount > 0))
1112 try_return( ntStatus);
1115 if ( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1116 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1120 // Directory Entry Processing
1122 // First pass is performed with the TreeLock held shared.
1123 // If we detect any objects in use, we give up quickly without
1124 // making any changes and without blocking other threads.
1125 // The second pass is performed with the TreeLock held exclusive
1126 // so deletions can take place.
1129 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1133 try_return( ntStatus);
1136 KeQueryTickCount( &liCurrentTime);
1138 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1140 while( pCurrentDirEntry != NULL)
1143 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1144 pCurrentDirEntry->NameArrayReferenceCount > 0)
1147 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1149 try_return( ntStatus);
1152 if ( pCurrentDirEntry->ObjectInformation != NULL)
1155 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1156 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1159 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1161 try_return( ntStatus);
1164 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1165 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1166 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1169 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1171 try_return( ntStatus);
1174 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1177 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1183 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1190 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1193 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1194 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1202 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1205 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1207 if( pCurrentDirEntry != NULL)
1210 try_return( ntStatus);
1214 // Attempt the second pass with the TreeLock held exclusive.
1215 // The the TreeLock cannot be obtained without blocking it means that
1216 // the directory is in active use, so do nothing.
1219 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1223 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1226 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1228 try_return( ntStatus);
1231 KeQueryTickCount( &liCurrentTime);
1233 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1235 while( pCurrentDirEntry != NULL)
1238 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1244 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1250 if ( pCurrentDirEntry->ObjectInformation != NULL)
1253 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1254 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1260 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1261 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1262 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1268 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1271 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1277 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1284 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1287 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1288 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1296 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1299 if( pCurrentDirEntry != NULL)
1303 // At least one entry in the directory is actively in use.
1304 // Drop the lock and exit without removing anything.
1307 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1309 try_return( ntStatus);
1313 // Third pass, process each directory entry and remove what we can.
1314 // The VolumeCB TreeLock and the ObjectInfo TreeLock are still held exclusive.
1317 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1319 while( pCurrentDirEntry != NULL)
1322 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1325 // Delete the DirectoryCB which in turn removes the DIRENTRY reference
1326 // count from the associated ObjectInfoCB. The reference count held above
1327 // may now be the only one left.
1330 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1331 AFS_TRACE_LEVEL_VERBOSE,
1332 "AFSExamineObjectInfo Deleting DE %wZ Object %p\n",
1333 &pCurrentDirEntry->NameInformation.FileName,
1334 pCurrentDirEntry->ObjectInformation));
1336 AFSDeleteDirEntry( pCurrentObject,
1339 pCurrentDirEntry = pNextDirEntry;
1343 // Clear our enumerated flag on this object so we retrieve info again on next access
1346 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1348 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1351 else if ( bVolumeObject == FALSE)
1357 if( pCurrentObject->ObjectReferenceCount > 1 ||
1358 pCurrentObject->Fcb != NULL &&
1359 pCurrentObject->Fcb->OpenReferenceCount > 0)
1362 try_return( ntStatus);
1365 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1368 KeQueryTickCount( &liCurrentTime);
1370 if( pCurrentObject->ObjectReferenceCount == 1 &&
1371 ( pCurrentObject->Fcb == NULL ||
1372 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1373 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1374 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1375 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1378 AFSRemoveFcb( &pCurrentObject->Fcb);
1380 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1382 lCount = AFSObjectInfoDecrement( pCurrentObject,
1383 AFS_OBJECT_REFERENCE_WORKER);
1385 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1386 AFS_TRACE_LEVEL_VERBOSE,
1387 "AFSExamineObjectInfo Decrement4 count on object %p Cnt %d\n",
1392 // The Volume TreeLock is held exclusive. Therefore, the ObjectReferenceCount
1393 // cannot change. It is therefore safe to delete the ObjectInfoCB
1396 AFSDeleteObjectInfo( &pCurrentObject);
1401 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1408 case AFS_FILE_TYPE_FILE:
1411 if( pCurrentObject->ObjectReferenceCount > 1 ||
1412 pCurrentObject->Fcb != NULL &&
1413 pCurrentObject->Fcb->OpenReferenceCount > 0)
1416 try_return( ntStatus);
1419 if( pCurrentObject->Fcb != NULL)
1422 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1425 // Dropping the VolumeCB TreeLock permits the
1426 // pCurrentObject->ObjectReferenceCount to change.
1427 // But it cannot be held across the AFSCleanupFcb
1431 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1434 if (!AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1438 *pbReleaseVolumeLock = FALSE;
1441 if ( ntStatus == STATUS_RETRY ||
1442 *pbReleaseVolumeLock == FALSE)
1446 // The Fcb is in use.
1449 try_return( ntStatus);
1454 // VolumeCB is held exclusive
1457 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1460 KeQueryTickCount( &liCurrentTime);
1462 if( pCurrentObject->ObjectReferenceCount == 1 &&
1463 ( pCurrentObject->Fcb == NULL ||
1464 ( pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1465 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount == 0)) &&
1466 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1467 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1468 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1471 AFSRemoveFcb( &pCurrentObject->Fcb);
1473 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1475 lCount = AFSObjectInfoDecrement( pCurrentObject,
1476 AFS_OBJECT_REFERENCE_WORKER);
1478 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1479 AFS_TRACE_LEVEL_VERBOSE,
1480 "AFSExamineObjectInfo Decrement5 count on object %p Cnt %d\n",
1485 // The VolumeCB TreeLock is held exclusive so the
1486 // ObjectReferenceCount cannot change.
1489 AFSDeleteObjectInfo( &pCurrentObject);
1494 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1503 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1506 KeQueryTickCount( &liCurrentTime);
1508 if( pCurrentObject->ObjectReferenceCount == 1 &&
1509 ( pCurrentObject->Fcb == NULL ||
1510 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1511 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1512 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1513 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1516 AFSRemoveFcb( &pCurrentObject->Fcb);
1518 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1520 lCount = AFSObjectInfoDecrement( pCurrentObject,
1521 AFS_OBJECT_REFERENCE_WORKER);
1523 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1524 AFS_TRACE_LEVEL_VERBOSE,
1525 "AFSExamineObjectInfo Decrement6 count on object %p Cnt %d\n",
1530 // The VolumeCB TreeLock is held exclusive so the
1531 // ObjectReferenceCount cannot change.
1534 AFSDeleteObjectInfo( &pCurrentObject);
1539 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1546 if ( pCurrentObject != NULL)
1549 lCount = AFSObjectInfoDecrement( pCurrentObject,
1550 AFS_OBJECT_REFERENCE_WORKER);
1552 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1553 AFS_TRACE_LEVEL_VERBOSE,
1554 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1562 // Called with VolumeCB->VolumeLock held shared.
1566 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1568 NTSTATUS ntStatus = STATUS_SUCCESS;
1569 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1570 BOOLEAN bReleaseVolumeTreeLock = FALSE;
1571 BOOLEAN bVolumeObject = FALSE;
1575 // The Volume ObjectInfoTree TreeLock must be held exclusive to
1576 // prevent other threads from obtaining a reference to an ObjectInfoCB
1577 // via AFSFindObjectInfo() while it is being deleted. This is
1578 // annoying but the alternative is to hold the TreeLock shared during
1579 // garbage collection and exclusive during find operations.
1582 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1586 bReleaseVolumeTreeLock = TRUE;
1588 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1590 lCount = AFSObjectInfoIncrement( pCurrentObject,
1591 AFS_OBJECT_REFERENCE_WORKER);
1593 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1594 AFS_TRACE_LEVEL_VERBOSE,
1595 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1601 while( pCurrentObject != NULL &&
1602 bReleaseVolumeTreeLock == TRUE)
1605 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1608 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1611 // If the end of the VolumeCB ObjectInfo List is reached, then
1612 // the next ObjectInformationCB to examine is the one embedded within
1613 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1615 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1616 // is being examined.
1619 if( pNextObject == NULL &&
1620 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1623 pNextObject = &pVolumeCB->ObjectInformation;
1626 bVolumeObject = FALSE;
1631 lCount = AFSObjectInfoIncrement( pNextObject,
1632 AFS_OBJECT_REFERENCE_WORKER);
1634 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1635 AFS_TRACE_LEVEL_VERBOSE,
1636 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1646 bVolumeObject = TRUE;
1649 AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeTreeLock);
1651 if ( bReleaseVolumeTreeLock == TRUE &&
1652 ( ExGetExclusiveWaiterCount( pVolumeCB->ObjectInfoTree.TreeLock) > 0 ||
1653 ExGetSharedWaiterCount( pVolumeCB->ObjectInfoTree.TreeLock) > 0))
1656 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1658 bReleaseVolumeTreeLock = FALSE;
1661 // The CurrentObject is either destroyed or the reference count has been
1662 // dropped by AFSExamineObjectInfo().
1665 if ( bReleaseVolumeTreeLock == FALSE)
1669 // Try to obtain the Volume's ObjectInfoTree.TreeLock after dropping
1670 // other locks and continue.
1673 bReleaseVolumeTreeLock = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1677 pCurrentObject = pNextObject;
1682 if ( pCurrentObject != NULL)
1685 lCount = AFSObjectInfoDecrement( pCurrentObject,
1686 AFS_OBJECT_REFERENCE_WORKER);
1688 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1689 AFS_TRACE_LEVEL_VERBOSE,
1690 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1695 if( bReleaseVolumeTreeLock)
1698 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1704 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1707 UNREFERENCED_PARAMETER(Context);
1708 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1709 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1710 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1711 LARGE_INTEGER DueTime;
1714 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1717 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1718 AFS_TRACE_LEVEL_VERBOSE,
1719 "AFSPrimaryVolumeWorkerThread Initialized\n"));
1722 // Initialize the timer for the worker thread
1725 DueTime.QuadPart = -(5000);
1729 KeInitializeTimerEx( &Timer,
1730 SynchronizationTimer);
1732 KeSetTimerEx( &Timer,
1738 // Indicate that we are initialized and ready
1741 KeSetEvent( &pPoolContext->WorkerThreadReady,
1746 // Indicate we are initialized
1749 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1751 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1754 KeWaitForSingleObject( &Timer,
1761 // This is the primary volume worker so it will traverse the volume list
1762 // looking for cleanup or volumes requiring private workers
1765 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1768 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1770 while( pVolumeCB != NULL)
1773 if( pVolumeCB == AFSGlobalRoot ||
1774 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1778 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1783 if( pVolumeCB->ObjectInfoListHead == NULL)
1786 AFSReleaseResource( pVolumeCB->VolumeLock);
1788 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1790 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1793 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1796 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1800 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1802 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1804 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1809 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1811 AFSAcquireExcl( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1815 // If VolumeCB is idle, the Volume can be garbage collected
1818 if( pVolumeCB->ObjectInfoListHead == NULL &&
1819 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1820 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1821 pVolumeCB->VolumeReferenceCount == 0 &&
1822 ( pVolumeCB->RootFcb == NULL ||
1823 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1824 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1827 AFSRemoveRootFcb( pVolumeCB);
1829 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1831 AFSRemoveVolume( pVolumeCB);
1836 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1838 AFSReleaseResource( pVolumeCB->VolumeLock);
1841 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1843 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1845 pVolumeCB = pNextVolume;
1851 // Don't need this lock anymore now that we have a volume cb to work with
1854 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1857 // For now we only need the volume lock shared
1860 AFSConvertToShared( pVolumeCB->VolumeLock);
1862 AFSExamineVolume( pVolumeCB);
1868 AFSReleaseResource( pVolumeCB->VolumeLock);
1870 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1873 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1876 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1878 } // worker thread loop
1880 KeCancelTimer( &Timer);
1882 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1884 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1885 AFS_TRACE_LEVEL_VERBOSE,
1886 "AFSPrimaryVolumeWorkerThread Exiting\n"));
1888 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1893 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1898 PsTerminateSystemThread( 0);
1904 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1907 NTSTATUS ntStatus = STATUS_SUCCESS;
1908 AFSDeviceExt *pControlDevExt = NULL;
1911 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1913 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1914 AFS_TRACE_LEVEL_VERBOSE,
1915 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1916 &pControlDevExt->Specific.Control.QueueLock,
1917 PsGetCurrentThread()));
1919 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1922 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1924 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1925 AFS_TRACE_LEVEL_VERBOSE,
1926 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1930 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1933 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1938 pControlDevExt->Specific.Control.QueueHead = WorkItem;
1941 WorkItem->next = NULL;
1942 pControlDevExt->Specific.Control.QueueTail = WorkItem;
1944 // indicate that the queue has nodes
1945 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
1949 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
1955 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1958 NTSTATUS ntStatus = STATUS_SUCCESS;
1959 AFSDeviceExt *pControlDevExt = NULL;
1962 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1964 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1965 AFS_TRACE_LEVEL_VERBOSE,
1966 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1967 &pControlDevExt->Specific.Control.IOQueueLock,
1968 PsGetCurrentThread()));
1970 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
1973 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
1975 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1976 AFS_TRACE_LEVEL_VERBOSE,
1977 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
1981 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
1984 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
1989 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
1992 WorkItem->next = NULL;
1993 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
1995 // indicate that the queue has nodes
1996 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2000 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2006 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2009 NTSTATUS ntStatus = STATUS_SUCCESS;
2010 AFSDeviceExt *pControlDevExt = NULL;
2013 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2015 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2016 AFS_TRACE_LEVEL_VERBOSE,
2017 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2018 &pControlDevExt->Specific.Control.QueueLock,
2019 PsGetCurrentThread()));
2021 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2024 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2026 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2028 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2030 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2031 AFS_TRACE_LEVEL_VERBOSE,
2032 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2037 // indicate that the queue has nodes
2040 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2044 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2053 AFSWorkItem *pWorkItem = NULL;
2054 AFSDeviceExt *pControlDevExt = NULL;
2057 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2059 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2060 AFS_TRACE_LEVEL_VERBOSE,
2061 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2062 &pControlDevExt->Specific.Control.QueueLock,
2063 PsGetCurrentThread()));
2065 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2068 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2071 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2073 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2075 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2076 AFS_TRACE_LEVEL_VERBOSE,
2077 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2080 PsGetCurrentThreadId()));
2082 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2084 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2087 pControlDevExt->Specific.Control.QueueTail = NULL;
2093 // Wake up another worker
2096 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2102 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2108 AFSRemoveIOWorkItem()
2111 AFSWorkItem *pWorkItem = NULL;
2112 AFSDeviceExt *pControlDevExt = NULL;
2115 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2117 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2118 AFS_TRACE_LEVEL_VERBOSE,
2119 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2120 &pControlDevExt->Specific.Control.IOQueueLock,
2121 PsGetCurrentThread()));
2123 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2126 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2129 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2131 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2133 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2134 AFS_TRACE_LEVEL_VERBOSE,
2135 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2138 PsGetCurrentThreadId()));
2140 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2142 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2145 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2151 // Wake up another worker
2154 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2160 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2166 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2169 NTSTATUS ntStatus = STATUS_SUCCESS;
2170 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2173 // Submit the work item to the worker
2176 ntStatus = AFSInsertWorkitem( WorkItem);
2182 // Sync request so block on the work item event
2185 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2196 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2199 NTSTATUS ntStatus = STATUS_SUCCESS;
2200 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2203 // Submit the work item to the worker
2206 ntStatus = AFSInsertIOWorkitem( WorkItem);
2212 // Sync request so block on the work item event
2215 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2226 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2229 NTSTATUS ntStatus = STATUS_SUCCESS;
2230 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2233 // Submit the work item to the worker
2236 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2242 // Sync request so block on the work item event
2245 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2256 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2260 NTSTATUS ntStatus = STATUS_SUCCESS;
2261 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2262 AFSWorkItem *pWorkItem = NULL;
2268 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2269 AFS_TRACE_LEVEL_VERBOSE,
2270 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2271 Fcb->ObjectInformation->FileId.Cell,
2272 Fcb->ObjectInformation->FileId.Volume,
2273 Fcb->ObjectInformation->FileId.Vnode,
2274 Fcb->ObjectInformation->FileId.Unique));
2277 // Increment our flush count here just to keep the number of items in the
2278 // queue down. We'll decrement it just below.
2281 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2286 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2287 AFS_TRACE_LEVEL_VERBOSE,
2288 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2289 Fcb->ObjectInformation->FileId.Cell,
2290 Fcb->ObjectInformation->FileId.Volume,
2291 Fcb->ObjectInformation->FileId.Vnode,
2292 Fcb->ObjectInformation->FileId.Unique));
2294 try_return( ntStatus);
2297 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2300 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2301 AFS_TRACE_LEVEL_ERROR,
2302 "AFSQueueFlushExtents Failing request, in shutdown\n"));
2304 try_return( ntStatus = STATUS_TOO_LATE);
2308 // Allocate our request structure and send it to the worker
2311 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2312 sizeof( AFSWorkItem),
2315 if( pWorkItem == NULL)
2318 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2319 AFS_TRACE_LEVEL_ERROR,
2320 "AFSQueueFlushExtents Failed to allocate work item\n"));
2322 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2325 RtlZeroMemory( pWorkItem,
2326 sizeof( AFSWorkItem));
2328 pWorkItem->Size = sizeof( AFSWorkItem);
2330 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2332 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2334 if ( AuthGroup == NULL)
2337 RtlZeroMemory( &pWorkItem->AuthGroup,
2340 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2343 &pWorkItem->AuthGroup);
2347 RtlCopyMemory( &pWorkItem->AuthGroup,
2352 pWorkItem->Specific.Fcb.Fcb = Fcb;
2354 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2356 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2357 AFS_TRACE_LEVEL_VERBOSE,
2358 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2362 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2363 AFS_TRACE_LEVEL_VERBOSE,
2364 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2366 Fcb->ObjectInformation->FileId.Cell,
2367 Fcb->ObjectInformation->FileId.Volume,
2368 Fcb->ObjectInformation->FileId.Vnode,
2369 Fcb->ObjectInformation->FileId.Unique));
2371 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2375 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2376 AFS_TRACE_LEVEL_VERBOSE,
2377 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2378 Fcb->ObjectInformation->FileId.Cell,
2379 Fcb->ObjectInformation->FileId.Volume,
2380 Fcb->ObjectInformation->FileId.Vnode,
2381 Fcb->ObjectInformation->FileId.Unique,
2385 // Remove the count we added above
2388 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2390 ASSERT( lCount >= 0);
2395 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2400 if( !NT_SUCCESS( ntStatus))
2403 if( pWorkItem != NULL)
2406 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2408 AFSExFreePoolWithTag( pWorkItem,
2412 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2413 AFS_TRACE_LEVEL_ERROR,
2414 "AFSQueueFlushExtents Failed to queue request Status %08lX\n",
2418 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2423 "EXCEPTION - AFSQueueFlushExtents\n"));
2425 AFSDumpTraceFilesFnc();
2432 AFSQueueGlobalRootEnumeration()
2435 NTSTATUS ntStatus = STATUS_SUCCESS;
2436 AFSWorkItem *pWorkItem = NULL;
2441 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2442 sizeof(AFSWorkItem),
2444 if (NULL == pWorkItem)
2447 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2448 AFS_TRACE_LEVEL_ERROR,
2449 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n"));
2451 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2454 RtlZeroMemory( pWorkItem,
2455 sizeof(AFSWorkItem));
2457 pWorkItem->Size = sizeof( AFSWorkItem);
2459 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2461 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2462 AFS_TRACE_LEVEL_VERBOSE,
2463 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2466 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2470 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2471 AFS_TRACE_LEVEL_VERBOSE,
2472 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2475 if( !NT_SUCCESS( ntStatus))
2478 if( pWorkItem != NULL)
2481 AFSExFreePoolWithTag( pWorkItem,
2485 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2486 AFS_TRACE_LEVEL_ERROR,
2487 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2491 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2496 "EXCEPTION - AFSQueueGlobalRootEnumeration\n"));
2498 AFSDumpTraceFilesFnc();
2505 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2506 IN UCHAR FunctionCode,
2507 IN ULONG RequestFlags,
2508 IN AFSIoRun *IoRuns,
2510 IN AFSGatherIo *GatherIo)
2513 NTSTATUS ntStatus = STATUS_SUCCESS;
2514 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2515 AFSWorkItem *pWorkItem = NULL;
2520 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2523 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2524 AFS_TRACE_LEVEL_ERROR,
2525 "AFSQueueStartIos Failing request, in shutdown\n"));
2527 try_return( ntStatus = STATUS_TOO_LATE);
2531 // Allocate our request structure and send it to the worker
2534 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2535 sizeof( AFSWorkItem),
2538 if( pWorkItem == NULL)
2541 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2542 AFS_TRACE_LEVEL_ERROR,
2543 "AFSQueueStartIos Failed to allocate work item\n"));
2545 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2548 RtlZeroMemory( pWorkItem,
2549 sizeof( AFSWorkItem));
2551 KeInitializeEvent( &pWorkItem->Event,
2555 pWorkItem->Size = sizeof( AFSWorkItem);
2557 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2559 pWorkItem->RequestType = AFS_WORK_START_IOS;
2561 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2563 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2565 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2567 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2569 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2571 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2573 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2574 AFS_TRACE_LEVEL_VERBOSE,
2575 "AFSQueueStartIos Queuing IO Workitem %p\n",
2578 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2582 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2583 AFS_TRACE_LEVEL_VERBOSE,
2584 "AFSQueueStartIos Request complete Status %08lX\n",
2587 if( !NT_SUCCESS( ntStatus))
2590 if( pWorkItem != NULL)
2593 AFSExFreePoolWithTag( pWorkItem,
2598 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2603 "EXCEPTION - AFSQueueStartIos\n"));
2605 AFSDumpTraceFilesFnc();
2612 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2613 IN ULONG InvalidateReason)
2616 NTSTATUS ntStatus = STATUS_SUCCESS;
2617 AFSWorkItem *pWorkItem = NULL;
2622 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2623 sizeof(AFSWorkItem),
2625 if (NULL == pWorkItem)
2628 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2629 AFS_TRACE_LEVEL_ERROR,
2630 "AFSQueueInvalidateObject Failed to allocate work item\n"));
2632 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2635 RtlZeroMemory( pWorkItem,
2636 sizeof(AFSWorkItem));
2638 pWorkItem->Size = sizeof( AFSWorkItem);
2640 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2642 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2644 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2646 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2647 AFS_TRACE_LEVEL_VERBOSE,
2648 "AFSQueueInvalidateObject Workitem %p\n",
2651 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2655 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2656 AFS_TRACE_LEVEL_VERBOSE,
2657 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2660 if( !NT_SUCCESS( ntStatus))
2663 if( pWorkItem != NULL)
2666 AFSExFreePoolWithTag( pWorkItem,
2670 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2671 AFS_TRACE_LEVEL_ERROR,
2672 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2676 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2681 "EXCEPTION - AFSQueueInvalidateObject\n"));
2683 AFSDumpTraceFilesFnc();
2690 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2691 IN PFILE_OBJECT FileObject,
2692 IN HANDLE CallingUser,
2694 IN ULONG BytesToWrite,
2695 IN BOOLEAN bRetrying)
2697 NTSTATUS ntStatus = STATUS_SUCCESS;
2698 AFSWorkItem *pWorkItem = NULL;
2704 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2708 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2711 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2712 AFS_TRACE_LEVEL_ERROR,
2713 "%s Could not pin user memory item\n",
2716 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2719 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2720 sizeof(AFSWorkItem),
2723 if (NULL == pWorkItem)
2726 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2727 AFS_TRACE_LEVEL_ERROR,
2728 "%s Failed to allocate work item\n",
2731 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2734 RtlZeroMemory( pWorkItem,
2735 sizeof(AFSWorkItem));
2737 pWorkItem->Size = sizeof( AFSWorkItem);
2739 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2741 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2743 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2745 pWorkItem->Specific.AsynchIo.Irp = Irp;
2747 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2748 AFS_TRACE_LEVEL_VERBOSE,
2753 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2755 IoMarkIrpPending(Irp);
2757 ntStatus = STATUS_PENDING;
2759 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2764 "EXCEPTION - %s \n",
2767 ntStatus = GetExceptionCode();
2772 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2773 AFS_TRACE_LEVEL_VERBOSE,
2774 "%s complete Status %08lX\n",
2778 if( !NT_SUCCESS( ntStatus))
2781 if( pWorkItem != NULL)
2784 AFSExFreePoolWithTag( pWorkItem,
2788 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2789 AFS_TRACE_LEVEL_ERROR,
2790 "%s Failed to queue request Status %08lX\n",
2800 AFSPostedDeferredWrite( IN PVOID Context1,
2803 UNREFERENCED_PARAMETER( Context2);
2806 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2808 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2809 AFS_TRACE_LEVEL_ERROR,
2814 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2816 if (!NT_SUCCESS( ntStatus))
2819 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2821 AFSExFreePoolWithTag( pWorkItem,
2824 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2825 AFS_TRACE_LEVEL_ERROR,
2826 "%s (%p) Failed to queue request Status %08lX\n",
2828 pWorkItem->Specific.AsynchIo.Irp,