2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSWorker.cpp
39 #include "AFSCommon.h"
43 AFSPostedDeferredWrite( IN PVOID Context1,
47 // Function: AFSInitializeWorkerPool
51 // This function initializes the worker thread pool
55 // A status is returned for the function
59 AFSInitializeWorkerPool()
62 NTSTATUS ntStatus = STATUS_SUCCESS;
63 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
64 AFSDeviceExt *pDevExt = NULL;
69 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
72 // Initialize the worker threads.
75 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
78 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
79 sizeof( AFSWorkQueueContext),
82 if( pCurrentWorker == NULL)
85 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
86 AFS_TRACE_LEVEL_ERROR,
87 "AFSInitializeWorkerPool Failed to allocate worker context\n"));
89 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
94 RtlZeroMemory( pCurrentWorker,
95 sizeof( AFSWorkQueueContext));
97 ntStatus = AFSInitWorkerThread( pCurrentWorker,
98 (PKSTART_ROUTINE)AFSWorkerThread);
100 if( !NT_SUCCESS( ntStatus))
103 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
104 AFS_TRACE_LEVEL_ERROR,
105 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n",
108 ExFreePool( pCurrentWorker);
113 if( pDevExt->Specific.Library.PoolHead == NULL)
116 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
121 pLastWorker->fLink = pCurrentWorker;
124 pLastWorker = pCurrentWorker;
126 pDevExt->Specific.Library.WorkerCount++;
130 // If there was a failure but there is at least one worker, then go with it.
133 if( !NT_SUCCESS( ntStatus) &&
134 pDevExt->Specific.Library.WorkerCount == 0)
137 try_return( ntStatus);
140 ntStatus = STATUS_SUCCESS;
143 // Now our IO Worker queue
146 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
149 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
150 sizeof( AFSWorkQueueContext),
153 if( pCurrentWorker == NULL)
156 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
157 AFS_TRACE_LEVEL_ERROR,
158 "AFSInitializeWorkerPool Failed to allocate IO worker context\n"));
160 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
165 RtlZeroMemory( pCurrentWorker,
166 sizeof( AFSWorkQueueContext));
168 ntStatus = AFSInitWorkerThread( pCurrentWorker,
169 (PKSTART_ROUTINE)AFSIOWorkerThread);
171 if( !NT_SUCCESS( ntStatus))
174 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
175 AFS_TRACE_LEVEL_ERROR,
176 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n",
179 ExFreePool( 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 ExFreePool( pCurrentWorker);
288 pCurrentWorker = pNextWorker;
290 if( pCurrentWorker == NULL)
299 pDevExt->Specific.Library.PoolHead = NULL;
302 // Loop through the IO workers shutting them down in two stages.
303 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
304 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
305 // to wake the workers and wait for them to exit.
308 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
312 while( index < pDevExt->Specific.Library.IOWorkerCount)
315 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
317 pCurrentWorker = pCurrentWorker->fLink;
319 if ( pCurrentWorker == NULL)
328 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
332 while( index < pDevExt->Specific.Library.IOWorkerCount)
335 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
337 pNextWorker = pCurrentWorker->fLink;
339 ExFreePool( pCurrentWorker);
341 pCurrentWorker = pNextWorker;
343 if( pCurrentWorker == NULL)
352 pDevExt->Specific.Library.IOPoolHead = NULL;
358 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
361 NTSTATUS ntStatus = STATUS_SUCCESS;
362 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
364 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
365 PKSTART_ROUTINE pStartRoutine = NULL;
371 if ( VolumeCB != AFSGlobalRoot)
374 return STATUS_INVALID_PARAMETER;
377 pStartRoutine = AFSPrimaryVolumeWorkerThread;
380 // Initialize the worker thread
383 KeInitializeEvent( &pWorker->WorkerThreadReady,
388 // Set the worker to process requests
391 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
397 ntStatus = PsCreateSystemThread( &hThread,
405 if( NT_SUCCESS( ntStatus))
408 ObReferenceObjectByHandle( hThread,
409 GENERIC_READ | GENERIC_WRITE,
412 (PVOID *)&pWorker->WorkerThreadObject,
415 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
421 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
426 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
437 // Function: AFSInitWorkerThread
441 // This function initializes a worker thread in the pool
445 // A status is returned for the function
449 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
450 IN PKSTART_ROUTINE WorkerRoutine)
453 NTSTATUS ntStatus = STATUS_SUCCESS;
457 // INitialize the worker signal thread
460 KeInitializeEvent( &PoolContext->WorkerThreadReady,
465 // Set the worker to process requests
468 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
474 ntStatus = PsCreateSystemThread( &Handle,
480 (void *)PoolContext);
482 if( NT_SUCCESS( ntStatus))
485 ObReferenceObjectByHandle( Handle,
486 GENERIC_READ | GENERIC_WRITE,
489 (PVOID *)&PoolContext->WorkerThreadObject,
492 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
505 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
508 NTSTATUS ntStatus = STATUS_SUCCESS;
509 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
512 // Clear the 'keep processing' flag
515 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
517 if( pWorker->WorkerThreadObject != NULL)
519 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
522 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
529 ObDereferenceObject( pWorker->WorkerThreadObject);
531 pWorker->WorkerThreadObject = NULL;
538 // Function: AFSShutdownWorkerThread
542 // This function shutsdown a worker thread in the pool
546 // A status is returned for the function
550 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
553 NTSTATUS ntStatus = STATUS_SUCCESS;
554 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
556 if( PoolContext->WorkerThreadObject != NULL)
559 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
563 // Wake up the thread if it is a sleep
566 KeSetEvent( &pControlDeviceExt->Specific.Control.WorkerQueueHasItems,
570 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
577 ObDereferenceObject( PoolContext->WorkerThreadObject);
579 PoolContext->WorkerThreadObject = NULL;
586 // Function: AFSShutdownIOWorkerThread
590 // This function shutsdown an IO worker thread in the pool
594 // A status is returned for the function
598 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
601 NTSTATUS ntStatus = STATUS_SUCCESS;
602 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
604 if( PoolContext->WorkerThreadObject != NULL)
607 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
611 // Wake up the thread if it is a sleep
614 KeSetEvent( &pControlDeviceExt->Specific.Control.IOWorkerQueueHasItems,
618 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
625 ObDereferenceObject( PoolContext->WorkerThreadObject);
627 PoolContext->WorkerThreadObject = NULL;
634 // Function: AFSWorkerThread
638 // This is the worker thread entry point.
642 // A status is returned for the function
646 AFSWorkerThread( IN PVOID Context)
649 NTSTATUS ntStatus = STATUS_SUCCESS;
650 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
651 AFSWorkItem *pWorkItem;
652 BOOLEAN freeWorkItem = TRUE;
653 AFSDeviceExt *pControlDevExt = NULL;
656 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
659 // Indicate that we are initialized and ready
662 KeSetEvent( &pPoolContext->WorkerThreadReady,
667 // Indicate we are initialized
670 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
672 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
678 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
681 if( !NT_SUCCESS( ntStatus))
684 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
685 AFS_TRACE_LEVEL_ERROR,
686 "AFSWorkerThread Wait for queue items failed Status %08lX\n",
689 ntStatus = STATUS_SUCCESS;
694 pWorkItem = AFSRemoveWorkItem();
696 if( pWorkItem == NULL)
699 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
711 // Switch on the type of work item to process
714 switch( pWorkItem->RequestType)
717 case AFS_WORK_FLUSH_FCB:
720 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
721 &pWorkItem->AuthGroup);
723 if( !NT_SUCCESS( ntStatus))
726 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
727 &pWorkItem->AuthGroup,
731 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
733 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
738 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
741 AFSEnumerateGlobalRoot( NULL);
746 case AFS_WORK_INVALIDATE_OBJECT:
749 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
750 pWorkItem->Specific.Invalidate.InvalidateReason);
757 case AFS_WORK_START_IOS:
767 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
768 AFS_TRACE_LEVEL_ERROR,
769 "AFSWorkerThread Unknown request type %d\n",
770 pWorkItem->RequestType));
778 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
781 ntStatus = STATUS_SUCCESS;
784 } // worker thread loop
786 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
788 // Wake up another worker so they too can exit
790 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
794 PsTerminateSystemThread( 0);
800 AFSIOWorkerThread( IN PVOID Context)
803 NTSTATUS ntStatus = STATUS_SUCCESS;
804 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
805 AFSWorkItem *pWorkItem;
806 BOOLEAN freeWorkItem = TRUE;
807 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
809 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
812 // Indicate that we are initialized and ready
815 KeSetEvent( &pPoolContext->WorkerThreadReady,
821 // Indicate we are initialized
824 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
826 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
832 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
835 if( !NT_SUCCESS( ntStatus))
838 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
839 AFS_TRACE_LEVEL_ERROR,
840 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n",
843 ntStatus = STATUS_SUCCESS;
848 pWorkItem = AFSRemoveIOWorkItem();
850 if( pWorkItem == NULL)
853 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
865 // Switch on the type of work item to process
868 switch( pWorkItem->RequestType)
871 case AFS_WORK_START_IOS:
874 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
877 // The final status is in the gather io
880 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
881 pWorkItem->Specific.CacheAccess.FunctionCode,
882 pWorkItem->Specific.CacheAccess.RequestFlags,
883 pWorkItem->Specific.CacheAccess.IoRuns,
884 pWorkItem->Specific.CacheAccess.RunCount,
885 pWorkItem->Specific.CacheAccess.GatherIo);
888 // Regardless of the status we we do the complete - there may
890 // Decrement the count - setting the event if we were told
891 // to. This may trigger completion.
894 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
901 case AFS_WORK_DEFERRED_WRITE:
904 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
905 pWorkItem->Specific.AsynchIo.Irp,
906 pWorkItem->Specific.AsynchIo.CallingProcess,
916 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
917 AFS_TRACE_LEVEL_ERROR,
918 "AFSIOWorkerThread Unknown request type %d\n",
919 pWorkItem->RequestType));
927 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
930 ntStatus = STATUS_SUCCESS;
933 } // worker thread loop
935 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
937 // Wake up another IOWorker so they too can exit
939 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
943 PsTerminateSystemThread( 0);
949 AFSExamineDirectory( IN AFSObjectInfoCB * pCurrentObject,
950 IN AFSDirectoryCB * pCurrentDirEntry)
954 AFSObjectInfoCB *pCurrentChildObject = NULL;
955 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
956 BOOLEAN bFcbBusy = FALSE;
959 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
961 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
962 AFS_TRACE_LEVEL_VERBOSE,
963 "AFSExamineDirectory Deleting DE %wZ Object %p\n",
964 &pCurrentDirEntry->NameInformation.FileName,
965 pCurrentChildObject));
967 AFSDeleteDirEntry( pCurrentObject,
970 if ( pCurrentChildObject != NULL)
974 // Acquire ObjectInfoLock shared here so as not to deadlock
975 // with an invalidation call from the service during AFSCleanupFcb
978 lCount = AFSObjectInfoIncrement( pCurrentChildObject,
979 AFS_OBJECT_REFERENCE_WORKER);
981 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
982 AFS_TRACE_LEVEL_VERBOSE,
983 "AFSExamineDirectory Increment count on object %p Cnt %d\n",
988 pCurrentChildObject->Fcb != NULL &&
989 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
993 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
994 // across an AFSCleanupFcb call since it can deadlock with an
995 // invalidation call from the service.
998 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1001 // Cannot hold a TreeLock across an AFSCleanupFcb call
1002 // as it can deadlock with an invalidation ioctl initiated
1003 // from the service.
1005 // Dropping the TreeLock permits the
1006 // pCurrentObject->ObjectReferenceCount to change
1009 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1012 if ( ntStatus == STATUS_RETRY)
1018 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1022 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1025 lCount = AFSObjectInfoDecrement( pCurrentChildObject,
1026 AFS_OBJECT_REFERENCE_WORKER);
1028 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1029 AFS_TRACE_LEVEL_VERBOSE,
1030 "AFSExamineDirectory Decrement1 count on object %p Cnt %d\n",
1031 pCurrentChildObject,
1035 pCurrentChildObject->Fcb != NULL &&
1036 pCurrentChildObject->Fcb->OpenReferenceCount == 0)
1039 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1041 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1042 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1045 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1048 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1050 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1052 AFSDeleteObjectInfo( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1054 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1056 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1058 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1059 AFS_TRACE_LEVEL_VERBOSE,
1060 "AFSExamineDirectory (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1061 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB));
1063 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1066 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1068 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1069 AFS_TRACE_LEVEL_VERBOSE,
1070 "AFSExamineDirectory Deleting object %p\n",
1071 pCurrentChildObject));
1073 AFSDeleteObjectInfo( &pCurrentChildObject);
1078 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1086 // Called with VolumeCB->ObjectInfoTree.TreeLock held shared.
1087 // The TreeLock will be released unless *pbReleaseVolumeLock is set to FALSE.
1091 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
1092 IN BOOLEAN bVolumeObject,
1093 IN OUT BOOLEAN * pbReleaseVolumeLock)
1095 NTSTATUS ntStatus = STATUS_SUCCESS;
1096 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1097 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1098 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
1099 AFSObjectInfoCB *pCurrentChildObject = NULL;
1100 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
1101 LARGE_INTEGER liCurrentTime;
1102 BOOLEAN bFcbBusy = FALSE;
1106 switch ( pCurrentObject->FileType) {
1108 case AFS_FILE_TYPE_DIRECTORY:
1111 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1118 // If this object is deleted then remove it from the parent, if we can
1121 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1122 pCurrentObject->ObjectReferenceCount <= 0 &&
1123 ( pCurrentObject->Fcb == NULL ||
1124 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1125 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1126 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1129 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1132 // Dropping the TreeLock permits the
1133 // pCurrentObject->ObjectReferenceCount to change
1136 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1140 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1143 if ( pCurrentObject->ObjectReferenceCount <= 0)
1146 AFSRemoveFcb( &pCurrentObject->Fcb);
1148 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1151 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1154 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1156 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1158 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1160 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1162 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1164 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1165 AFS_TRACE_LEVEL_VERBOSE,
1166 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1167 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB));
1169 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1172 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1174 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1175 AFS_TRACE_LEVEL_VERBOSE,
1176 "AFSExamineObjectInfo Deleting deleted object %p\n",
1179 AFSDeleteObjectInfo( &pCurrentObject);
1184 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1187 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1192 *pbReleaseVolumeLock = FALSE;
1198 if ( pCurrentObject->Fcb != NULL &&
1199 pCurrentObject->Fcb->CcbListHead != NULL)
1204 for ( pCcb = pCurrentObject->Fcb->CcbListHead;
1206 pCcb = (AFSCcb *)pCcb->ListEntry.fLink)
1209 if ( pCcb->NameArray) {
1211 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1212 AFS_TRACE_LEVEL_VERBOSE,
1213 "AFSExamineObjectInfo Found Object %p Fcb %p Ccb %p\n",
1215 pCurrentObject->Fcb,
1223 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1224 ( pCurrentObject->Fcb != NULL &&
1225 pCurrentObject->Fcb->OpenReferenceCount > 0))
1231 if ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
1232 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1235 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1242 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1245 // Directory Entry Processing
1248 KeQueryTickCount( &liCurrentTime);
1250 while( pCurrentDirEntry != NULL)
1253 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1259 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1265 if ( pCurrentDirEntry->ObjectInformation != NULL)
1268 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1269 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1275 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1276 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1277 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1283 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1286 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1292 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1299 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1302 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1303 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1311 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1314 if( pCurrentDirEntry != NULL)
1317 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1322 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1324 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1327 // Now acquire the locks excl without deadlocking
1330 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1334 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1338 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1340 *pbReleaseVolumeLock = FALSE;
1345 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1348 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1350 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1355 KeQueryTickCount( &liCurrentTime);
1357 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1359 while( pCurrentDirEntry != NULL)
1362 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1368 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1374 if ( pCurrentDirEntry->ObjectInformation != NULL)
1377 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1378 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1384 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1385 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1386 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1392 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1395 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1401 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1408 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1411 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1412 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1420 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1423 if( pCurrentDirEntry != NULL)
1426 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1428 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1433 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1435 while( pCurrentDirEntry != NULL)
1438 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1440 AFSExamineDirectory( pCurrentObject,
1443 pCurrentDirEntry = pNextDirEntry;
1447 // Clear our enumerated flag on this object so we retrieve info again on next access
1450 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1452 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1454 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1460 // Try to grab the volume lock again ... no problem if we don't
1463 if( !AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1467 *pbReleaseVolumeLock = FALSE;
1473 else if ( bVolumeObject == FALSE)
1479 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1481 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1485 *pbReleaseVolumeLock = FALSE;
1490 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1493 KeQueryTickCount( &liCurrentTime);
1495 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1496 ( pCurrentObject->Fcb == NULL ||
1497 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1498 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1499 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1500 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1503 AFSRemoveFcb( &pCurrentObject->Fcb);
1505 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1507 AFSDeleteObjectInfo( &pCurrentObject);
1512 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1515 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1520 case AFS_FILE_TYPE_FILE:
1523 lCount = AFSObjectInfoIncrement( pCurrentObject,
1524 AFS_OBJECT_REFERENCE_WORKER);
1526 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1527 AFS_TRACE_LEVEL_VERBOSE,
1528 "AFSExamineObjectInfo Increment3 count on object %p Cnt %d\n",
1532 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1534 if( pCurrentObject->Fcb != NULL)
1538 // Dropping the TreeLock permits the
1539 // pCurrentObject->ObjectReferenceCount to change
1542 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1545 if ( ntStatus == STATUS_RETRY)
1552 bTemp = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1555 lCount = AFSObjectInfoDecrement( pCurrentObject,
1556 AFS_OBJECT_REFERENCE_WORKER);
1558 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1559 AFS_TRACE_LEVEL_VERBOSE,
1560 "AFSExamineObjectInfo Decrement3 count on object %p Cnt %d\n",
1564 if ( bTemp == FALSE)
1567 *pbReleaseVolumeLock = FALSE;
1572 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1575 KeQueryTickCount( &liCurrentTime);
1577 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1578 ( pCurrentObject->Fcb == NULL ||
1579 ( pCurrentObject->Fcb->OpenReferenceCount <= 0 &&
1580 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount <= 0)) &&
1581 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1582 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1583 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1586 AFSRemoveFcb( &pCurrentObject->Fcb);
1588 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1590 AFSDeleteObjectInfo( &pCurrentObject);
1595 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1598 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1605 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1607 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1611 *pbReleaseVolumeLock = FALSE;
1616 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1619 KeQueryTickCount( &liCurrentTime);
1621 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1622 ( pCurrentObject->Fcb == NULL ||
1623 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1624 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1625 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1626 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1629 AFSRemoveFcb( &pCurrentObject->Fcb);
1631 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1633 AFSDeleteObjectInfo( &pCurrentObject);
1638 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1641 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1650 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1652 NTSTATUS ntStatus = STATUS_SUCCESS;
1653 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1654 BOOLEAN bReleaseVolumeLock = FALSE;
1655 BOOLEAN bVolumeObject = FALSE;
1656 BOOLEAN bFcbBusy = FALSE;
1659 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1663 bReleaseVolumeLock = TRUE;
1665 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1669 while( pCurrentObject != NULL)
1672 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1675 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1678 // If the end of the VolumeCB ObjectInfo List is reached, then
1679 // the next ObjectInformationCB to examine is the one embedded within
1680 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1682 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1683 // is being examined.
1686 if( pNextObject == NULL &&
1687 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1690 pNextObject = &pVolumeCB->ObjectInformation;
1693 bVolumeObject = FALSE;
1698 lCount = AFSObjectInfoIncrement( pNextObject,
1699 AFS_OBJECT_REFERENCE_WORKER);
1701 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1702 AFS_TRACE_LEVEL_VERBOSE,
1703 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1713 bVolumeObject = TRUE;
1716 bFcbBusy = AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeLock);
1721 lCount = AFSObjectInfoDecrement( pNextObject,
1722 AFS_OBJECT_REFERENCE_WORKER);
1724 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1725 AFS_TRACE_LEVEL_VERBOSE,
1726 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1732 // If AFSExamineObjectInfo drops the VolumeLock before returning
1733 // we must halt processing of the Volume's ObjectInfo list.
1736 if ( bReleaseVolumeLock == FALSE)
1742 pCurrentObject = pNextObject;
1745 if( bReleaseVolumeLock)
1748 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1756 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1759 UNREFERENCED_PARAMETER(Context);
1760 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1761 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1762 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1763 LARGE_INTEGER DueTime;
1766 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1767 BOOLEAN bFcbBusy = FALSE;
1770 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1771 AFS_TRACE_LEVEL_VERBOSE,
1772 "AFSPrimaryVolumeWorkerThread Initialized\n"));
1775 // Initialize the timer for the worker thread
1778 DueTime.QuadPart = -(5000);
1782 KeInitializeTimerEx( &Timer,
1783 SynchronizationTimer);
1785 KeSetTimerEx( &Timer,
1791 // Indicate that we are initialized and ready
1794 KeSetEvent( &pPoolContext->WorkerThreadReady,
1799 // Indicate we are initialized
1802 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1804 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1807 if ( bFcbBusy == FALSE)
1810 KeWaitForSingleObject( &Timer,
1823 // This is the primary volume worker so it will traverse the volume list
1824 // looking for cleanup or volumes requiring private workers
1827 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1830 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1832 while( pVolumeCB != NULL)
1835 if( pVolumeCB == AFSGlobalRoot ||
1836 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1840 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1845 if( pVolumeCB->ObjectInfoListHead == NULL)
1848 AFSReleaseResource( pVolumeCB->VolumeLock);
1850 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1852 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1855 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1858 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1862 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1864 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1866 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1871 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1873 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1877 // If VolumeCB is idle, the Volume can be garbage collected
1880 if( pVolumeCB->ObjectInfoListHead == NULL &&
1881 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1882 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1883 pVolumeCB->VolumeReferenceCount == 0 &&
1884 ( pVolumeCB->RootFcb == NULL ||
1885 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1886 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1889 AFSRemoveRootFcb( pVolumeCB);
1891 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1893 AFSRemoveVolume( pVolumeCB);
1898 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1900 AFSReleaseResource( pVolumeCB->VolumeLock);
1903 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1905 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1907 pVolumeCB = pNextVolume;
1913 // Don't need this lock anymore now that we have a volume cb to work with
1916 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1919 // For now we only need the volume lock shared
1922 AFSConvertToShared( pVolumeCB->VolumeLock);
1924 AFSExamineVolume( pVolumeCB);
1930 AFSReleaseResource( pVolumeCB->VolumeLock);
1932 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1935 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1938 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1940 } // worker thread loop
1942 KeCancelTimer( &Timer);
1944 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1946 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1947 AFS_TRACE_LEVEL_VERBOSE,
1948 "AFSPrimaryVolumeWorkerThread Exiting\n"));
1950 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1955 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1960 PsTerminateSystemThread( 0);
1966 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1969 NTSTATUS ntStatus = STATUS_SUCCESS;
1970 AFSDeviceExt *pControlDevExt = NULL;
1973 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1975 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1976 AFS_TRACE_LEVEL_VERBOSE,
1977 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1978 &pControlDevExt->Specific.Control.QueueLock,
1979 PsGetCurrentThread()));
1981 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1984 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1986 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1987 AFS_TRACE_LEVEL_VERBOSE,
1988 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1992 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1995 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
2000 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2003 WorkItem->next = NULL;
2004 pControlDevExt->Specific.Control.QueueTail = WorkItem;
2006 // indicate that the queue has nodes
2007 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2011 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2017 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
2020 NTSTATUS ntStatus = STATUS_SUCCESS;
2021 AFSDeviceExt *pControlDevExt = NULL;
2024 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2026 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2027 AFS_TRACE_LEVEL_VERBOSE,
2028 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2029 &pControlDevExt->Specific.Control.IOQueueLock,
2030 PsGetCurrentThread()));
2032 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2035 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2037 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2038 AFS_TRACE_LEVEL_VERBOSE,
2039 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
2043 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
2046 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
2051 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
2054 WorkItem->next = NULL;
2055 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
2057 // indicate that the queue has nodes
2058 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2062 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2068 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2071 NTSTATUS ntStatus = STATUS_SUCCESS;
2072 AFSDeviceExt *pControlDevExt = NULL;
2075 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2077 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2078 AFS_TRACE_LEVEL_VERBOSE,
2079 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2080 &pControlDevExt->Specific.Control.QueueLock,
2081 PsGetCurrentThread()));
2083 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2086 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2088 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2090 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2092 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2093 AFS_TRACE_LEVEL_VERBOSE,
2094 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2099 // indicate that the queue has nodes
2102 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2106 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2115 AFSWorkItem *pWorkItem = NULL;
2116 AFSDeviceExt *pControlDevExt = NULL;
2119 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2121 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2122 AFS_TRACE_LEVEL_VERBOSE,
2123 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2124 &pControlDevExt->Specific.Control.QueueLock,
2125 PsGetCurrentThread()));
2127 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2130 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2133 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2135 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2137 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2138 AFS_TRACE_LEVEL_VERBOSE,
2139 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2142 PsGetCurrentThreadId()));
2144 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2146 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2149 pControlDevExt->Specific.Control.QueueTail = NULL;
2155 // Wake up another worker
2158 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2164 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2170 AFSRemoveIOWorkItem()
2173 AFSWorkItem *pWorkItem = NULL;
2174 AFSDeviceExt *pControlDevExt = NULL;
2177 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2179 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2180 AFS_TRACE_LEVEL_VERBOSE,
2181 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2182 &pControlDevExt->Specific.Control.IOQueueLock,
2183 PsGetCurrentThread()));
2185 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2188 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2191 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2193 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2195 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2196 AFS_TRACE_LEVEL_VERBOSE,
2197 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2200 PsGetCurrentThreadId()));
2202 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2204 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2207 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2213 // Wake up another worker
2216 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2222 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2228 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2231 NTSTATUS ntStatus = STATUS_SUCCESS;
2232 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2235 // Submit the work item to the worker
2238 ntStatus = AFSInsertWorkitem( WorkItem);
2244 // Sync request so block on the work item event
2247 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2258 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2261 NTSTATUS ntStatus = STATUS_SUCCESS;
2262 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2265 // Submit the work item to the worker
2268 ntStatus = AFSInsertIOWorkitem( WorkItem);
2274 // Sync request so block on the work item event
2277 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2288 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2291 NTSTATUS ntStatus = STATUS_SUCCESS;
2292 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2295 // Submit the work item to the worker
2298 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2304 // Sync request so block on the work item event
2307 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2318 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2322 NTSTATUS ntStatus = STATUS_SUCCESS;
2323 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2324 AFSWorkItem *pWorkItem = NULL;
2330 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2331 AFS_TRACE_LEVEL_VERBOSE,
2332 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2333 Fcb->ObjectInformation->FileId.Cell,
2334 Fcb->ObjectInformation->FileId.Volume,
2335 Fcb->ObjectInformation->FileId.Vnode,
2336 Fcb->ObjectInformation->FileId.Unique));
2339 // Increment our flush count here just to keep the number of items in the
2340 // queue down. We'll decrement it just below.
2343 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2348 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2349 AFS_TRACE_LEVEL_VERBOSE,
2350 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2351 Fcb->ObjectInformation->FileId.Cell,
2352 Fcb->ObjectInformation->FileId.Volume,
2353 Fcb->ObjectInformation->FileId.Vnode,
2354 Fcb->ObjectInformation->FileId.Unique));
2356 try_return( ntStatus);
2359 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2362 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2363 AFS_TRACE_LEVEL_ERROR,
2364 "AFSQueueFlushExtents Failing request, in shutdown\n"));
2366 try_return( ntStatus = STATUS_TOO_LATE);
2370 // Allocate our request structure and send it to the worker
2373 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2374 sizeof( AFSWorkItem),
2377 if( pWorkItem == NULL)
2380 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2381 AFS_TRACE_LEVEL_ERROR,
2382 "AFSQueueFlushExtents Failed to allocate work item\n"));
2384 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2387 RtlZeroMemory( pWorkItem,
2388 sizeof( AFSWorkItem));
2390 pWorkItem->Size = sizeof( AFSWorkItem);
2392 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2394 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2396 if ( AuthGroup == NULL)
2399 RtlZeroMemory( &pWorkItem->AuthGroup,
2402 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2405 &pWorkItem->AuthGroup);
2409 RtlCopyMemory( &pWorkItem->AuthGroup,
2414 pWorkItem->Specific.Fcb.Fcb = Fcb;
2416 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2418 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2419 AFS_TRACE_LEVEL_VERBOSE,
2420 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2424 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2425 AFS_TRACE_LEVEL_VERBOSE,
2426 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2428 Fcb->ObjectInformation->FileId.Cell,
2429 Fcb->ObjectInformation->FileId.Volume,
2430 Fcb->ObjectInformation->FileId.Vnode,
2431 Fcb->ObjectInformation->FileId.Unique));
2433 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2437 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2438 AFS_TRACE_LEVEL_VERBOSE,
2439 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2440 Fcb->ObjectInformation->FileId.Cell,
2441 Fcb->ObjectInformation->FileId.Volume,
2442 Fcb->ObjectInformation->FileId.Vnode,
2443 Fcb->ObjectInformation->FileId.Unique,
2447 // Remove the count we added above
2450 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2452 ASSERT( lCount >= 0);
2457 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2462 if( !NT_SUCCESS( ntStatus))
2465 if( pWorkItem != NULL)
2468 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2470 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2473 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2474 AFS_TRACE_LEVEL_ERROR,
2475 "AFSQueueFlushExtents Failed to queue request Status %08lX\n",
2479 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2484 "EXCEPTION - AFSQueueFlushExtents\n"));
2486 AFSDumpTraceFilesFnc();
2493 AFSQueueGlobalRootEnumeration()
2496 NTSTATUS ntStatus = STATUS_SUCCESS;
2497 AFSWorkItem *pWorkItem = NULL;
2502 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2503 sizeof(AFSWorkItem),
2505 if (NULL == pWorkItem)
2508 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2509 AFS_TRACE_LEVEL_ERROR,
2510 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n"));
2512 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2515 RtlZeroMemory( pWorkItem,
2516 sizeof(AFSWorkItem));
2518 pWorkItem->Size = sizeof( AFSWorkItem);
2520 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2522 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2523 AFS_TRACE_LEVEL_VERBOSE,
2524 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2527 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2531 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2532 AFS_TRACE_LEVEL_VERBOSE,
2533 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2536 if( !NT_SUCCESS( ntStatus))
2539 if( pWorkItem != NULL)
2542 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2545 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2546 AFS_TRACE_LEVEL_ERROR,
2547 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2551 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2556 "EXCEPTION - AFSQueueGlobalRootEnumeration\n"));
2558 AFSDumpTraceFilesFnc();
2565 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2566 IN UCHAR FunctionCode,
2567 IN ULONG RequestFlags,
2568 IN AFSIoRun *IoRuns,
2570 IN AFSGatherIo *GatherIo)
2573 NTSTATUS ntStatus = STATUS_SUCCESS;
2574 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2575 AFSWorkItem *pWorkItem = NULL;
2580 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2583 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2584 AFS_TRACE_LEVEL_ERROR,
2585 "AFSQueueStartIos Failing request, in shutdown\n"));
2587 try_return( ntStatus = STATUS_TOO_LATE);
2591 // Allocate our request structure and send it to the worker
2594 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2595 sizeof( AFSWorkItem),
2598 if( pWorkItem == NULL)
2601 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2602 AFS_TRACE_LEVEL_ERROR,
2603 "AFSQueueStartIos Failed to allocate work item\n"));
2605 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2608 RtlZeroMemory( pWorkItem,
2609 sizeof( AFSWorkItem));
2611 KeInitializeEvent( &pWorkItem->Event,
2615 pWorkItem->Size = sizeof( AFSWorkItem);
2617 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2619 pWorkItem->RequestType = AFS_WORK_START_IOS;
2621 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2623 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2625 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2627 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2629 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2631 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2633 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2634 AFS_TRACE_LEVEL_VERBOSE,
2635 "AFSQueueStartIos Queuing IO Workitem %p\n",
2638 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2642 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2643 AFS_TRACE_LEVEL_VERBOSE,
2644 "AFSQueueStartIos Request complete Status %08lX\n",
2647 if( !NT_SUCCESS( ntStatus))
2650 if( pWorkItem != NULL)
2653 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2657 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2662 "EXCEPTION - AFSQueueStartIos\n"));
2664 AFSDumpTraceFilesFnc();
2671 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2672 IN ULONG InvalidateReason)
2675 NTSTATUS ntStatus = STATUS_SUCCESS;
2676 AFSWorkItem *pWorkItem = NULL;
2681 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2682 sizeof(AFSWorkItem),
2684 if (NULL == pWorkItem)
2687 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2688 AFS_TRACE_LEVEL_ERROR,
2689 "AFSQueueInvalidateObject Failed to allocate work item\n"));
2691 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2694 RtlZeroMemory( pWorkItem,
2695 sizeof(AFSWorkItem));
2697 pWorkItem->Size = sizeof( AFSWorkItem);
2699 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2701 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2703 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2705 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2706 AFS_TRACE_LEVEL_VERBOSE,
2707 "AFSQueueInvalidateObject Workitem %p\n",
2710 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2714 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2715 AFS_TRACE_LEVEL_VERBOSE,
2716 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2719 if( !NT_SUCCESS( ntStatus))
2722 if( pWorkItem != NULL)
2724 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2727 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2728 AFS_TRACE_LEVEL_ERROR,
2729 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2733 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2738 "EXCEPTION - AFSQueueInvalidateObject\n"));
2740 AFSDumpTraceFilesFnc();
2747 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2748 IN PFILE_OBJECT FileObject,
2749 IN HANDLE CallingUser,
2751 IN ULONG BytesToWrite,
2752 IN BOOLEAN bRetrying)
2754 NTSTATUS ntStatus = STATUS_SUCCESS;
2755 AFSWorkItem *pWorkItem = NULL;
2761 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2765 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2768 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2769 AFS_TRACE_LEVEL_ERROR,
2770 "%s Could not pin user memory item\n",
2773 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2776 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2777 sizeof(AFSWorkItem),
2780 if (NULL == pWorkItem)
2783 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2784 AFS_TRACE_LEVEL_ERROR,
2785 "%s Failed to allocate work item\n",
2788 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2791 RtlZeroMemory( pWorkItem,
2792 sizeof(AFSWorkItem));
2794 pWorkItem->Size = sizeof( AFSWorkItem);
2796 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2798 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2800 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2802 pWorkItem->Specific.AsynchIo.Irp = Irp;
2804 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2805 AFS_TRACE_LEVEL_VERBOSE,
2810 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2812 IoMarkIrpPending(Irp);
2814 ntStatus = STATUS_PENDING;
2816 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2821 "EXCEPTION - %s \n",
2824 ntStatus = GetExceptionCode();
2829 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2830 AFS_TRACE_LEVEL_VERBOSE,
2831 "%s complete Status %08lX\n",
2835 if( !NT_SUCCESS( ntStatus))
2838 if( pWorkItem != NULL)
2841 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2844 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2845 AFS_TRACE_LEVEL_ERROR,
2846 "%s Failed to queue request Status %08lX\n",
2856 AFSPostedDeferredWrite( IN PVOID Context1,
2859 UNREFERENCED_PARAMETER( Context2);
2862 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2864 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2865 AFS_TRACE_LEVEL_ERROR,
2870 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2872 if (!NT_SUCCESS( ntStatus))
2875 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2877 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2879 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2880 AFS_TRACE_LEVEL_ERROR,
2881 "%s (%p) Failed to queue request Status %08lX\n",
2883 pWorkItem->Specific.AsynchIo.Irp,