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 ExFreePool( pCurrentWorker);
111 if( pDevExt->Specific.Library.PoolHead == NULL)
114 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
119 pLastWorker->fLink = pCurrentWorker;
122 pLastWorker = pCurrentWorker;
124 pDevExt->Specific.Library.WorkerCount++;
128 // If there was a failure but there is at least one worker, then go with it.
131 if( !NT_SUCCESS( ntStatus) &&
132 pDevExt->Specific.Library.WorkerCount == 0)
135 try_return( ntStatus);
138 ntStatus = STATUS_SUCCESS;
141 // Now our IO Worker queue
144 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
147 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
148 sizeof( AFSWorkQueueContext),
151 if( pCurrentWorker == NULL)
154 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
155 AFS_TRACE_LEVEL_ERROR,
156 "AFSInitializeWorkerPool Failed to allocate IO worker context\n"));
158 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
163 RtlZeroMemory( pCurrentWorker,
164 sizeof( AFSWorkQueueContext));
166 ntStatus = AFSInitWorkerThread( pCurrentWorker,
167 (PKSTART_ROUTINE)AFSIOWorkerThread);
169 if( !NT_SUCCESS( ntStatus))
172 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
173 AFS_TRACE_LEVEL_ERROR,
174 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n",
177 ExFreePool( pCurrentWorker);
182 if( pDevExt->Specific.Library.IOPoolHead == NULL)
185 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
190 pLastWorker->fLink = pCurrentWorker;
193 pLastWorker = pCurrentWorker;
195 pDevExt->Specific.Library.IOWorkerCount++;
199 // If there was a failure but there is at least one worker, then go with it.
202 if( !NT_SUCCESS( ntStatus) &&
203 pDevExt->Specific.Library.IOWorkerCount == 0)
206 try_return( ntStatus);
211 if( !NT_SUCCESS( ntStatus))
215 // Failed to initialize the pool so tear it down
218 AFSRemoveWorkerPool();
226 // Function: AFSRemoveWorkerPool
230 // This function tears down the worker thread pool
234 // A status is returned for the function
238 AFSRemoveWorkerPool()
241 NTSTATUS ntStatus = STATUS_SUCCESS;
243 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
244 AFSDeviceExt *pDevExt = NULL;
246 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
249 // Loop through the workers shutting them down in two stages.
250 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
251 // stop processing requests. Second, call AFSShutdownWorkerThread()
252 // to wake the workers and wait for them to exit.
255 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
257 while( index < pDevExt->Specific.Library.WorkerCount)
260 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
262 pCurrentWorker = pCurrentWorker->fLink;
264 if ( pCurrentWorker == NULL)
273 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
277 while( index < pDevExt->Specific.Library.WorkerCount)
280 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
282 pNextWorker = pCurrentWorker->fLink;
284 ExFreePool( pCurrentWorker);
286 pCurrentWorker = pNextWorker;
288 if( pCurrentWorker == NULL)
297 pDevExt->Specific.Library.PoolHead = NULL;
300 // Loop through the IO workers shutting them down in two stages.
301 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
302 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
303 // to wake the workers and wait for them to exit.
306 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
310 while( index < pDevExt->Specific.Library.IOWorkerCount)
313 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
315 pCurrentWorker = pCurrentWorker->fLink;
317 if ( pCurrentWorker == NULL)
326 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
330 while( index < pDevExt->Specific.Library.IOWorkerCount)
333 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
335 pNextWorker = pCurrentWorker->fLink;
337 ExFreePool( pCurrentWorker);
339 pCurrentWorker = pNextWorker;
341 if( pCurrentWorker == NULL)
350 pDevExt->Specific.Library.IOPoolHead = NULL;
356 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
359 NTSTATUS ntStatus = STATUS_SUCCESS;
360 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
362 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
363 PKSTART_ROUTINE pStartRoutine = NULL;
369 if ( VolumeCB != AFSGlobalRoot)
372 return STATUS_INVALID_PARAMETER;
375 pStartRoutine = AFSPrimaryVolumeWorkerThread;
378 // Initialize the worker thread
381 KeInitializeEvent( &pWorker->WorkerThreadReady,
386 // Set the worker to process requests
389 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
395 ntStatus = PsCreateSystemThread( &hThread,
403 if( NT_SUCCESS( ntStatus))
406 ObReferenceObjectByHandle( hThread,
407 GENERIC_READ | GENERIC_WRITE,
410 (PVOID *)&pWorker->WorkerThreadObject,
413 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
419 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
424 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
435 // Function: AFSInitWorkerThread
439 // This function initializes a worker thread in the pool
443 // A status is returned for the function
447 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
448 IN PKSTART_ROUTINE WorkerRoutine)
451 NTSTATUS ntStatus = STATUS_SUCCESS;
455 // INitialize the worker signal thread
458 KeInitializeEvent( &PoolContext->WorkerThreadReady,
463 // Set the worker to process requests
466 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
472 ntStatus = PsCreateSystemThread( &Handle,
478 (void *)PoolContext);
480 if( NT_SUCCESS( ntStatus))
483 ObReferenceObjectByHandle( Handle,
484 GENERIC_READ | GENERIC_WRITE,
487 (PVOID *)&PoolContext->WorkerThreadObject,
490 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
503 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
506 NTSTATUS ntStatus = STATUS_SUCCESS;
507 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
510 // Clear the 'keep processing' flag
513 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
515 if( pWorker->WorkerThreadObject != NULL)
517 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
520 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
527 ObDereferenceObject( pWorker->WorkerThreadObject);
529 pWorker->WorkerThreadObject = NULL;
536 // Function: AFSShutdownWorkerThread
540 // This function shutsdown a worker thread in the pool
544 // A status is returned for the function
548 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
551 NTSTATUS ntStatus = STATUS_SUCCESS;
552 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
554 if( PoolContext->WorkerThreadObject != NULL)
557 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
561 // Wake up the thread if it is a sleep
564 KeSetEvent( &pControlDeviceExt->Specific.Control.WorkerQueueHasItems,
568 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
575 ObDereferenceObject( PoolContext->WorkerThreadObject);
577 PoolContext->WorkerThreadObject = NULL;
584 // Function: AFSShutdownIOWorkerThread
588 // This function shutsdown an IO worker thread in the pool
592 // A status is returned for the function
596 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
599 NTSTATUS ntStatus = STATUS_SUCCESS;
600 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
602 if( PoolContext->WorkerThreadObject != NULL)
605 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
609 // Wake up the thread if it is a sleep
612 KeSetEvent( &pControlDeviceExt->Specific.Control.IOWorkerQueueHasItems,
616 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
623 ObDereferenceObject( PoolContext->WorkerThreadObject);
625 PoolContext->WorkerThreadObject = NULL;
632 // Function: AFSWorkerThread
636 // This is the worker thread entry point.
640 // A status is returned for the function
644 AFSWorkerThread( IN PVOID Context)
647 NTSTATUS ntStatus = STATUS_SUCCESS;
648 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
649 AFSWorkItem *pWorkItem;
650 BOOLEAN freeWorkItem = TRUE;
651 AFSDeviceExt *pControlDevExt = NULL;
654 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
657 // Indicate that we are initialized and ready
660 KeSetEvent( &pPoolContext->WorkerThreadReady,
665 // Indicate we are initialized
668 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
670 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
676 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
679 if( !NT_SUCCESS( ntStatus))
682 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
683 AFS_TRACE_LEVEL_ERROR,
684 "AFSWorkerThread Wait for queue items failed Status %08lX\n",
687 ntStatus = STATUS_SUCCESS;
692 pWorkItem = AFSRemoveWorkItem();
694 if( pWorkItem == NULL)
697 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
709 // Switch on the type of work item to process
712 switch( pWorkItem->RequestType)
715 case AFS_WORK_FLUSH_FCB:
718 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
719 &pWorkItem->AuthGroup);
721 if( !NT_SUCCESS( ntStatus))
724 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
725 &pWorkItem->AuthGroup,
729 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
731 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
736 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
739 AFSEnumerateGlobalRoot( NULL);
744 case AFS_WORK_INVALIDATE_OBJECT:
747 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
748 pWorkItem->Specific.Invalidate.InvalidateReason);
755 case AFS_WORK_START_IOS:
765 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
766 AFS_TRACE_LEVEL_ERROR,
767 "AFSWorkerThread Unknown request type %d\n",
768 pWorkItem->RequestType));
776 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
779 ntStatus = STATUS_SUCCESS;
782 } // worker thread loop
784 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
786 // Wake up another worker so they too can exit
788 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
792 PsTerminateSystemThread( 0);
798 AFSIOWorkerThread( IN PVOID Context)
801 NTSTATUS ntStatus = STATUS_SUCCESS;
802 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
803 AFSWorkItem *pWorkItem;
804 BOOLEAN freeWorkItem = TRUE;
805 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
807 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
810 // Indicate that we are initialized and ready
813 KeSetEvent( &pPoolContext->WorkerThreadReady,
819 // Indicate we are initialized
822 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
824 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
830 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
833 if( !NT_SUCCESS( ntStatus))
836 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
837 AFS_TRACE_LEVEL_ERROR,
838 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n",
841 ntStatus = STATUS_SUCCESS;
846 pWorkItem = AFSRemoveIOWorkItem();
848 if( pWorkItem == NULL)
851 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
863 // Switch on the type of work item to process
866 switch( pWorkItem->RequestType)
869 case AFS_WORK_START_IOS:
872 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
875 // The final status is in the gather io
878 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
879 pWorkItem->Specific.CacheAccess.FunctionCode,
880 pWorkItem->Specific.CacheAccess.RequestFlags,
881 pWorkItem->Specific.CacheAccess.IoRuns,
882 pWorkItem->Specific.CacheAccess.RunCount,
883 pWorkItem->Specific.CacheAccess.GatherIo);
886 // Regardless of the status we we do the complete - there may
888 // Decrement the count - setting the event if we were told
889 // to. This may trigger completion.
892 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
899 case AFS_WORK_DEFERRED_WRITE:
902 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
903 pWorkItem->Specific.AsynchIo.Irp,
904 pWorkItem->Specific.AsynchIo.CallingProcess,
914 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
915 AFS_TRACE_LEVEL_ERROR,
916 "AFSIOWorkerThread Unknown request type %d\n",
917 pWorkItem->RequestType));
925 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
928 ntStatus = STATUS_SUCCESS;
931 } // worker thread loop
933 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
935 // Wake up another IOWorker so they too can exit
937 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
941 PsTerminateSystemThread( 0);
947 // Called with VolumeCB->ObjectInfoTree.TreeLock held exclusive.
948 // pCurrentObject->ObjectReferenceCount is incremented by the caller.
950 // The *pbReleaseVolumeLock is set to FALSE if the TreeLock is dropped
953 // pCurrentObject must either be destroyed or the reference count
954 // decremented before returning.
958 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
959 IN BOOLEAN bVolumeObject,
960 IN OUT BOOLEAN * pbReleaseVolumeLock)
962 NTSTATUS ntStatus = STATUS_SUCCESS;
963 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
964 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
965 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
966 AFSObjectInfoCB *pCurrentChildObject = NULL;
967 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
968 LARGE_INTEGER liCurrentTime;
975 ASSERT( ExIsResourceAcquiredExclusiveLite( pVolumeCB->ObjectInfoTree.TreeLock));
977 switch ( pCurrentObject->FileType)
980 case AFS_FILE_TYPE_DIRECTORY:
983 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
986 try_return( ntStatus);
990 // If this object is deleted then remove it from the parent, if we can
993 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED))
996 if ( pCurrentObject->ObjectReferenceCount == 1 &&
997 ( pCurrentObject->Fcb == NULL ||
998 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
999 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1000 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1003 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1006 if ( pCurrentObject->Fcb != NULL)
1009 AFSRemoveFcb( &pCurrentObject->Fcb);
1012 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1015 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1018 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1020 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1022 lCount = AFSObjectInfoDecrement( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1023 AFS_OBJECT_REFERENCE_PIOCTL);
1025 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1026 AFS_TRACE_LEVEL_VERBOSE,
1027 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1028 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation,
1031 ASSERT( lCount == 0);
1036 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1039 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1041 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1043 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1044 AFS_TRACE_LEVEL_VERBOSE,
1045 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1046 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB));
1048 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1050 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB = NULL;
1053 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1055 lCount = AFSObjectInfoDecrement( pCurrentObject,
1056 AFS_OBJECT_REFERENCE_WORKER);
1058 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1059 AFS_TRACE_LEVEL_VERBOSE,
1060 "AFSExamineObjectInfo Decrement1 count on object %p Cnt %d\n",
1064 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1065 AFS_TRACE_LEVEL_VERBOSE,
1066 "AFSExamineObjectInfo Deleting deleted object %p\n",
1070 // The CurrentReferenceCount must be zero or we would not
1071 // have gotten this far. It is safe to delete the ObjectInfoCB.
1074 AFSDeleteObjectInfo( &pCurrentObject);
1078 // Finished processing the AFS_OBJECT_FLAGS_DELETED case.
1081 try_return( ntStatus);
1085 // pCurrentObject not marked Deleted.
1088 if ( pCurrentObject->Fcb != NULL &&
1089 pCurrentObject->Fcb->CcbListHead != NULL)
1092 try_return( ntStatus);
1095 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1096 ( pCurrentObject->Fcb != NULL &&
1097 pCurrentObject->Fcb->OpenReferenceCount > 0))
1100 try_return( ntStatus);
1103 if ( pCurrentObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1104 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1108 // Directory Entry Processing
1110 // First pass is performed with the TreeLock held shared.
1111 // If we detect any objects in use, we give up quickly without
1112 // making any changes and without blocking other threads.
1113 // The second pass is performed with the TreeLock held exclusive
1114 // so deletions can take place.
1117 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1121 try_return( ntStatus);
1124 KeQueryTickCount( &liCurrentTime);
1126 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1128 while( pCurrentDirEntry != NULL)
1131 if( pCurrentDirEntry->DirOpenReferenceCount > 0 ||
1132 pCurrentDirEntry->NameArrayReferenceCount > 0)
1135 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1137 try_return( ntStatus);
1140 if ( pCurrentDirEntry->ObjectInformation != NULL)
1143 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1144 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1147 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1149 try_return( ntStatus);
1152 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1153 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1154 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1157 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1159 try_return( ntStatus);
1162 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1165 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1171 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1178 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1181 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1182 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1190 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1193 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1195 if( pCurrentDirEntry != NULL)
1198 try_return( ntStatus);
1202 // Attempt the second pass with the TreeLock held exclusive.
1203 // The the TreeLock cannot be obtained without blocking it means that
1204 // the directory is in active use, so do nothing.
1207 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1211 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1214 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1216 try_return( ntStatus);
1219 KeQueryTickCount( &liCurrentTime);
1221 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1223 while( pCurrentDirEntry != NULL)
1226 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1232 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1238 if ( pCurrentDirEntry->ObjectInformation != NULL)
1241 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1242 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1248 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1249 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1250 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1256 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1259 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1265 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1272 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1275 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1276 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1284 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1287 if( pCurrentDirEntry != NULL)
1291 // At least one entry in the directory is actively in use.
1292 // Drop the lock and exit without removing anything.
1295 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1297 try_return( ntStatus);
1301 // Third pass, process each directory entry and remove what we can.
1302 // The VolumeCB TreeLock and the ObjectInfo TreeLock are still held exclusive.
1305 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1307 while( pCurrentDirEntry != NULL)
1310 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1313 // Delete the DirectoryCB which in turn removes the DIRENTRY reference
1314 // count from the associated ObjectInfoCB. The reference count held above
1315 // may now be the only one left.
1318 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1319 AFS_TRACE_LEVEL_VERBOSE,
1320 "AFSExamineObjectInfo Deleting DE %wZ Object %p\n",
1321 &pCurrentDirEntry->NameInformation.FileName,
1322 pCurrentDirEntry->ObjectInformation));
1324 AFSDeleteDirEntry( pCurrentObject,
1327 pCurrentDirEntry = pNextDirEntry;
1331 // Clear our enumerated flag on this object so we retrieve info again on next access
1334 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1336 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1339 else if ( bVolumeObject == FALSE)
1345 if( pCurrentObject->ObjectReferenceCount > 1 ||
1346 pCurrentObject->Fcb != NULL &&
1347 pCurrentObject->Fcb->OpenReferenceCount > 0)
1350 try_return( ntStatus);
1353 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1356 KeQueryTickCount( &liCurrentTime);
1358 if( pCurrentObject->ObjectReferenceCount == 1 &&
1359 ( pCurrentObject->Fcb == NULL ||
1360 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1361 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1362 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1363 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1366 AFSRemoveFcb( &pCurrentObject->Fcb);
1368 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1370 lCount = AFSObjectInfoDecrement( pCurrentObject,
1371 AFS_OBJECT_REFERENCE_WORKER);
1373 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1374 AFS_TRACE_LEVEL_VERBOSE,
1375 "AFSExamineObjectInfo Decrement4 count on object %p Cnt %d\n",
1380 // The Volume TreeLock is held exclusive. Therefore, the ObjectReferenceCount
1381 // cannot change. It is therefore safe to delete the ObjectInfoCB
1384 AFSDeleteObjectInfo( &pCurrentObject);
1389 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1396 case AFS_FILE_TYPE_FILE:
1399 if( pCurrentObject->ObjectReferenceCount > 1 ||
1400 pCurrentObject->Fcb != NULL &&
1401 pCurrentObject->Fcb->OpenReferenceCount > 0)
1404 try_return( ntStatus);
1407 if( pCurrentObject->Fcb != NULL)
1410 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1413 // Dropping the VolumeCB TreeLock permits the
1414 // pCurrentObject->ObjectReferenceCount to change.
1415 // But it cannot be held across the AFSCleanupFcb
1419 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1422 if (!AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1426 *pbReleaseVolumeLock = FALSE;
1429 if ( ntStatus == STATUS_RETRY ||
1430 *pbReleaseVolumeLock == FALSE)
1434 // The Fcb is in use.
1437 try_return( ntStatus);
1442 // VolumeCB is held exclusive
1445 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1448 KeQueryTickCount( &liCurrentTime);
1450 if( pCurrentObject->ObjectReferenceCount == 1 &&
1451 ( pCurrentObject->Fcb == NULL ||
1452 ( pCurrentObject->Fcb->OpenReferenceCount == 0 &&
1453 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount == 0)) &&
1454 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1455 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1456 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1459 AFSRemoveFcb( &pCurrentObject->Fcb);
1461 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1463 lCount = AFSObjectInfoDecrement( pCurrentObject,
1464 AFS_OBJECT_REFERENCE_WORKER);
1466 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1467 AFS_TRACE_LEVEL_VERBOSE,
1468 "AFSExamineObjectInfo Decrement5 count on object %p Cnt %d\n",
1473 // The VolumeCB TreeLock is held exclusive so the
1474 // ObjectReferenceCount cannot change.
1477 AFSDeleteObjectInfo( &pCurrentObject);
1482 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1491 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1494 KeQueryTickCount( &liCurrentTime);
1496 if( pCurrentObject->ObjectReferenceCount == 1 &&
1497 ( pCurrentObject->Fcb == NULL ||
1498 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1499 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1500 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1501 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1504 AFSRemoveFcb( &pCurrentObject->Fcb);
1506 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1508 lCount = AFSObjectInfoDecrement( pCurrentObject,
1509 AFS_OBJECT_REFERENCE_WORKER);
1511 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1512 AFS_TRACE_LEVEL_VERBOSE,
1513 "AFSExamineObjectInfo Decrement6 count on object %p Cnt %d\n",
1518 // The VolumeCB TreeLock is held exclusive so the
1519 // ObjectReferenceCount cannot change.
1522 AFSDeleteObjectInfo( &pCurrentObject);
1527 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1534 if ( pCurrentObject != NULL)
1537 lCount = AFSObjectInfoDecrement( pCurrentObject,
1538 AFS_OBJECT_REFERENCE_WORKER);
1540 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1541 AFS_TRACE_LEVEL_VERBOSE,
1542 "AFSExamineObjectInfo Decrement count on object %p Cnt %d\n",
1550 // Called with VolumeCB->VolumeLock held shared.
1554 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1556 NTSTATUS ntStatus = STATUS_SUCCESS;
1557 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1558 BOOLEAN bReleaseVolumeTreeLock = FALSE;
1559 BOOLEAN bVolumeObject = FALSE;
1563 // The Volume ObjectInfoTree TreeLock must be held exclusive to
1564 // prevent other threads from obtaining a reference to an ObjectInfoCB
1565 // via AFSFindObjectInfo() while it is being deleted. This is
1566 // annoying but the alternative is to hold the TreeLock shared during
1567 // garbage collection and exclusive during find operations.
1570 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1574 bReleaseVolumeTreeLock = TRUE;
1576 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1578 lCount = AFSObjectInfoIncrement( pCurrentObject,
1579 AFS_OBJECT_REFERENCE_WORKER);
1581 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1582 AFS_TRACE_LEVEL_VERBOSE,
1583 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1589 while( pCurrentObject != NULL &&
1590 bReleaseVolumeTreeLock == TRUE)
1593 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1596 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1599 // If the end of the VolumeCB ObjectInfo List is reached, then
1600 // the next ObjectInformationCB to examine is the one embedded within
1601 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1603 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1604 // is being examined.
1607 if( pNextObject == NULL &&
1608 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1611 pNextObject = &pVolumeCB->ObjectInformation;
1614 bVolumeObject = FALSE;
1619 lCount = AFSObjectInfoIncrement( pNextObject,
1620 AFS_OBJECT_REFERENCE_WORKER);
1622 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1623 AFS_TRACE_LEVEL_VERBOSE,
1624 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1634 bVolumeObject = TRUE;
1637 AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeTreeLock);
1640 // The CurrentObject is either destroyed or the reference count has been
1641 // dropped by AFSExamineObjectInfo().
1644 if ( bReleaseVolumeTreeLock == FALSE)
1648 // Try to obtain the Volume's ObjectInfoTree.TreeLock after dropping
1649 // other locks and continue.
1652 bReleaseVolumeTreeLock = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1656 pCurrentObject = pNextObject;
1661 if ( pCurrentObject != NULL)
1664 lCount = AFSObjectInfoDecrement( pCurrentObject,
1665 AFS_OBJECT_REFERENCE_WORKER);
1667 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1668 AFS_TRACE_LEVEL_VERBOSE,
1669 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1674 if( bReleaseVolumeTreeLock)
1677 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1683 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1686 UNREFERENCED_PARAMETER(Context);
1687 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1688 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1689 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1690 LARGE_INTEGER DueTime;
1693 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1696 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1697 AFS_TRACE_LEVEL_VERBOSE,
1698 "AFSPrimaryVolumeWorkerThread Initialized\n"));
1701 // Initialize the timer for the worker thread
1704 DueTime.QuadPart = -(5000);
1708 KeInitializeTimerEx( &Timer,
1709 SynchronizationTimer);
1711 KeSetTimerEx( &Timer,
1717 // Indicate that we are initialized and ready
1720 KeSetEvent( &pPoolContext->WorkerThreadReady,
1725 // Indicate we are initialized
1728 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1730 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1733 KeWaitForSingleObject( &Timer,
1740 // This is the primary volume worker so it will traverse the volume list
1741 // looking for cleanup or volumes requiring private workers
1744 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1747 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1749 while( pVolumeCB != NULL)
1752 if( pVolumeCB == AFSGlobalRoot ||
1753 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1757 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1762 if( pVolumeCB->ObjectInfoListHead == NULL)
1765 AFSReleaseResource( pVolumeCB->VolumeLock);
1767 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1769 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1772 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1775 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1779 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1781 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1783 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1788 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1790 AFSAcquireExcl( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1794 // If VolumeCB is idle, the Volume can be garbage collected
1797 if( pVolumeCB->ObjectInfoListHead == NULL &&
1798 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1799 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1800 pVolumeCB->VolumeReferenceCount == 0 &&
1801 ( pVolumeCB->RootFcb == NULL ||
1802 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1803 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1806 AFSRemoveRootFcb( pVolumeCB);
1808 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1810 AFSRemoveVolume( pVolumeCB);
1815 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1817 AFSReleaseResource( pVolumeCB->VolumeLock);
1820 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1822 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1824 pVolumeCB = pNextVolume;
1830 // Don't need this lock anymore now that we have a volume cb to work with
1833 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1836 // For now we only need the volume lock shared
1839 AFSConvertToShared( pVolumeCB->VolumeLock);
1841 AFSExamineVolume( pVolumeCB);
1847 AFSReleaseResource( pVolumeCB->VolumeLock);
1849 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1852 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1855 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1857 } // worker thread loop
1859 KeCancelTimer( &Timer);
1861 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1863 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1864 AFS_TRACE_LEVEL_VERBOSE,
1865 "AFSPrimaryVolumeWorkerThread Exiting\n"));
1867 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1872 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1877 PsTerminateSystemThread( 0);
1883 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1886 NTSTATUS ntStatus = STATUS_SUCCESS;
1887 AFSDeviceExt *pControlDevExt = NULL;
1890 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1892 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1893 AFS_TRACE_LEVEL_VERBOSE,
1894 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1895 &pControlDevExt->Specific.Control.QueueLock,
1896 PsGetCurrentThread()));
1898 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1901 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1903 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1904 AFS_TRACE_LEVEL_VERBOSE,
1905 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1909 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1912 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1917 pControlDevExt->Specific.Control.QueueHead = WorkItem;
1920 WorkItem->next = NULL;
1921 pControlDevExt->Specific.Control.QueueTail = WorkItem;
1923 // indicate that the queue has nodes
1924 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
1928 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
1934 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
1937 NTSTATUS ntStatus = STATUS_SUCCESS;
1938 AFSDeviceExt *pControlDevExt = NULL;
1941 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1943 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1944 AFS_TRACE_LEVEL_VERBOSE,
1945 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1946 &pControlDevExt->Specific.Control.IOQueueLock,
1947 PsGetCurrentThread()));
1949 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
1952 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
1954 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1955 AFS_TRACE_LEVEL_VERBOSE,
1956 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
1960 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
1963 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
1968 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
1971 WorkItem->next = NULL;
1972 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
1974 // indicate that the queue has nodes
1975 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
1979 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
1985 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
1988 NTSTATUS ntStatus = STATUS_SUCCESS;
1989 AFSDeviceExt *pControlDevExt = NULL;
1992 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1994 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1995 AFS_TRACE_LEVEL_VERBOSE,
1996 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
1997 &pControlDevExt->Specific.Control.QueueLock,
1998 PsGetCurrentThread()));
2000 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2003 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2005 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2007 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2009 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2010 AFS_TRACE_LEVEL_VERBOSE,
2011 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2016 // indicate that the queue has nodes
2019 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2023 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2032 AFSWorkItem *pWorkItem = NULL;
2033 AFSDeviceExt *pControlDevExt = NULL;
2036 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2038 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2039 AFS_TRACE_LEVEL_VERBOSE,
2040 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2041 &pControlDevExt->Specific.Control.QueueLock,
2042 PsGetCurrentThread()));
2044 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2047 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2050 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2052 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2054 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2055 AFS_TRACE_LEVEL_VERBOSE,
2056 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2059 PsGetCurrentThreadId()));
2061 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2063 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2066 pControlDevExt->Specific.Control.QueueTail = NULL;
2072 // Wake up another worker
2075 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2081 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2087 AFSRemoveIOWorkItem()
2090 AFSWorkItem *pWorkItem = NULL;
2091 AFSDeviceExt *pControlDevExt = NULL;
2094 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2096 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2097 AFS_TRACE_LEVEL_VERBOSE,
2098 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2099 &pControlDevExt->Specific.Control.IOQueueLock,
2100 PsGetCurrentThread()));
2102 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2105 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2108 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2110 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2112 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2113 AFS_TRACE_LEVEL_VERBOSE,
2114 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2117 PsGetCurrentThreadId()));
2119 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2121 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2124 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2130 // Wake up another worker
2133 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2139 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2145 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2148 NTSTATUS ntStatus = STATUS_SUCCESS;
2149 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2152 // Submit the work item to the worker
2155 ntStatus = AFSInsertWorkitem( WorkItem);
2161 // Sync request so block on the work item event
2164 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2175 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2178 NTSTATUS ntStatus = STATUS_SUCCESS;
2179 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2182 // Submit the work item to the worker
2185 ntStatus = AFSInsertIOWorkitem( WorkItem);
2191 // Sync request so block on the work item event
2194 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2205 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2208 NTSTATUS ntStatus = STATUS_SUCCESS;
2209 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2212 // Submit the work item to the worker
2215 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2221 // Sync request so block on the work item event
2224 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2235 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2239 NTSTATUS ntStatus = STATUS_SUCCESS;
2240 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2241 AFSWorkItem *pWorkItem = NULL;
2247 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2248 AFS_TRACE_LEVEL_VERBOSE,
2249 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2250 Fcb->ObjectInformation->FileId.Cell,
2251 Fcb->ObjectInformation->FileId.Volume,
2252 Fcb->ObjectInformation->FileId.Vnode,
2253 Fcb->ObjectInformation->FileId.Unique));
2256 // Increment our flush count here just to keep the number of items in the
2257 // queue down. We'll decrement it just below.
2260 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2265 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2266 AFS_TRACE_LEVEL_VERBOSE,
2267 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2268 Fcb->ObjectInformation->FileId.Cell,
2269 Fcb->ObjectInformation->FileId.Volume,
2270 Fcb->ObjectInformation->FileId.Vnode,
2271 Fcb->ObjectInformation->FileId.Unique));
2273 try_return( ntStatus);
2276 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2279 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2280 AFS_TRACE_LEVEL_ERROR,
2281 "AFSQueueFlushExtents Failing request, in shutdown\n"));
2283 try_return( ntStatus = STATUS_TOO_LATE);
2287 // Allocate our request structure and send it to the worker
2290 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2291 sizeof( AFSWorkItem),
2294 if( pWorkItem == NULL)
2297 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2298 AFS_TRACE_LEVEL_ERROR,
2299 "AFSQueueFlushExtents Failed to allocate work item\n"));
2301 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2304 RtlZeroMemory( pWorkItem,
2305 sizeof( AFSWorkItem));
2307 pWorkItem->Size = sizeof( AFSWorkItem);
2309 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2311 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2313 if ( AuthGroup == NULL)
2316 RtlZeroMemory( &pWorkItem->AuthGroup,
2319 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2322 &pWorkItem->AuthGroup);
2326 RtlCopyMemory( &pWorkItem->AuthGroup,
2331 pWorkItem->Specific.Fcb.Fcb = Fcb;
2333 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2335 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2336 AFS_TRACE_LEVEL_VERBOSE,
2337 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2341 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2342 AFS_TRACE_LEVEL_VERBOSE,
2343 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2345 Fcb->ObjectInformation->FileId.Cell,
2346 Fcb->ObjectInformation->FileId.Volume,
2347 Fcb->ObjectInformation->FileId.Vnode,
2348 Fcb->ObjectInformation->FileId.Unique));
2350 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2354 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2355 AFS_TRACE_LEVEL_VERBOSE,
2356 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2357 Fcb->ObjectInformation->FileId.Cell,
2358 Fcb->ObjectInformation->FileId.Volume,
2359 Fcb->ObjectInformation->FileId.Vnode,
2360 Fcb->ObjectInformation->FileId.Unique,
2364 // Remove the count we added above
2367 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2369 ASSERT( lCount >= 0);
2374 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2379 if( !NT_SUCCESS( ntStatus))
2382 if( pWorkItem != NULL)
2385 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2387 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2390 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2391 AFS_TRACE_LEVEL_ERROR,
2392 "AFSQueueFlushExtents Failed to queue request Status %08lX\n",
2396 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2401 "EXCEPTION - AFSQueueFlushExtents\n"));
2403 AFSDumpTraceFilesFnc();
2410 AFSQueueGlobalRootEnumeration()
2413 NTSTATUS ntStatus = STATUS_SUCCESS;
2414 AFSWorkItem *pWorkItem = NULL;
2419 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2420 sizeof(AFSWorkItem),
2422 if (NULL == pWorkItem)
2425 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2426 AFS_TRACE_LEVEL_ERROR,
2427 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n"));
2429 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2432 RtlZeroMemory( pWorkItem,
2433 sizeof(AFSWorkItem));
2435 pWorkItem->Size = sizeof( AFSWorkItem);
2437 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2439 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2440 AFS_TRACE_LEVEL_VERBOSE,
2441 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2444 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2448 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2449 AFS_TRACE_LEVEL_VERBOSE,
2450 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2453 if( !NT_SUCCESS( ntStatus))
2456 if( pWorkItem != NULL)
2459 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2462 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2463 AFS_TRACE_LEVEL_ERROR,
2464 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2468 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2473 "EXCEPTION - AFSQueueGlobalRootEnumeration\n"));
2475 AFSDumpTraceFilesFnc();
2482 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2483 IN UCHAR FunctionCode,
2484 IN ULONG RequestFlags,
2485 IN AFSIoRun *IoRuns,
2487 IN AFSGatherIo *GatherIo)
2490 NTSTATUS ntStatus = STATUS_SUCCESS;
2491 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2492 AFSWorkItem *pWorkItem = NULL;
2497 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2500 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2501 AFS_TRACE_LEVEL_ERROR,
2502 "AFSQueueStartIos Failing request, in shutdown\n"));
2504 try_return( ntStatus = STATUS_TOO_LATE);
2508 // Allocate our request structure and send it to the worker
2511 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2512 sizeof( AFSWorkItem),
2515 if( pWorkItem == NULL)
2518 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2519 AFS_TRACE_LEVEL_ERROR,
2520 "AFSQueueStartIos Failed to allocate work item\n"));
2522 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2525 RtlZeroMemory( pWorkItem,
2526 sizeof( AFSWorkItem));
2528 KeInitializeEvent( &pWorkItem->Event,
2532 pWorkItem->Size = sizeof( AFSWorkItem);
2534 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2536 pWorkItem->RequestType = AFS_WORK_START_IOS;
2538 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2540 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2542 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2544 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2546 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2548 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2550 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2551 AFS_TRACE_LEVEL_VERBOSE,
2552 "AFSQueueStartIos Queuing IO Workitem %p\n",
2555 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2559 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2560 AFS_TRACE_LEVEL_VERBOSE,
2561 "AFSQueueStartIos Request complete Status %08lX\n",
2564 if( !NT_SUCCESS( ntStatus))
2567 if( pWorkItem != NULL)
2570 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2574 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2579 "EXCEPTION - AFSQueueStartIos\n"));
2581 AFSDumpTraceFilesFnc();
2588 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2589 IN ULONG InvalidateReason)
2592 NTSTATUS ntStatus = STATUS_SUCCESS;
2593 AFSWorkItem *pWorkItem = NULL;
2598 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2599 sizeof(AFSWorkItem),
2601 if (NULL == pWorkItem)
2604 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2605 AFS_TRACE_LEVEL_ERROR,
2606 "AFSQueueInvalidateObject Failed to allocate work item\n"));
2608 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2611 RtlZeroMemory( pWorkItem,
2612 sizeof(AFSWorkItem));
2614 pWorkItem->Size = sizeof( AFSWorkItem);
2616 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2618 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2620 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2622 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2623 AFS_TRACE_LEVEL_VERBOSE,
2624 "AFSQueueInvalidateObject Workitem %p\n",
2627 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2631 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2632 AFS_TRACE_LEVEL_VERBOSE,
2633 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2636 if( !NT_SUCCESS( ntStatus))
2639 if( pWorkItem != NULL)
2641 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2644 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2645 AFS_TRACE_LEVEL_ERROR,
2646 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2650 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2655 "EXCEPTION - AFSQueueInvalidateObject\n"));
2657 AFSDumpTraceFilesFnc();
2664 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2665 IN PFILE_OBJECT FileObject,
2666 IN HANDLE CallingUser,
2668 IN ULONG BytesToWrite,
2669 IN BOOLEAN bRetrying)
2671 NTSTATUS ntStatus = STATUS_SUCCESS;
2672 AFSWorkItem *pWorkItem = NULL;
2678 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2682 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2685 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2686 AFS_TRACE_LEVEL_ERROR,
2687 "%s Could not pin user memory item\n",
2690 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2693 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2694 sizeof(AFSWorkItem),
2697 if (NULL == pWorkItem)
2700 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2701 AFS_TRACE_LEVEL_ERROR,
2702 "%s Failed to allocate work item\n",
2705 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2708 RtlZeroMemory( pWorkItem,
2709 sizeof(AFSWorkItem));
2711 pWorkItem->Size = sizeof( AFSWorkItem);
2713 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2715 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2717 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2719 pWorkItem->Specific.AsynchIo.Irp = Irp;
2721 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2722 AFS_TRACE_LEVEL_VERBOSE,
2727 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2729 IoMarkIrpPending(Irp);
2731 ntStatus = STATUS_PENDING;
2733 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2738 "EXCEPTION - %s \n",
2741 ntStatus = GetExceptionCode();
2746 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2747 AFS_TRACE_LEVEL_VERBOSE,
2748 "%s complete Status %08lX\n",
2752 if( !NT_SUCCESS( ntStatus))
2755 if( pWorkItem != NULL)
2758 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2761 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2762 AFS_TRACE_LEVEL_ERROR,
2763 "%s Failed to queue request Status %08lX\n",
2773 AFSPostedDeferredWrite( IN PVOID Context1,
2776 UNREFERENCED_PARAMETER( Context2);
2779 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2781 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2782 AFS_TRACE_LEVEL_ERROR,
2787 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2789 if (!NT_SUCCESS( ntStatus))
2792 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2794 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2796 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2797 AFS_TRACE_LEVEL_ERROR,
2798 "%s (%p) Failed to queue request Status %08lX\n",
2800 pWorkItem->Specific.AsynchIo.Irp,