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 AFSDbgLogMsg( 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 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
104 AFS_TRACE_LEVEL_ERROR,
105 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n", ntStatus);
107 ExFreePool( pCurrentWorker);
112 if( pDevExt->Specific.Library.PoolHead == NULL)
115 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
120 pLastWorker->fLink = pCurrentWorker;
123 pLastWorker = pCurrentWorker;
125 pDevExt->Specific.Library.WorkerCount++;
129 // If there was a failure but there is at least one worker, then go with it.
132 if( !NT_SUCCESS( ntStatus) &&
133 pDevExt->Specific.Library.WorkerCount == 0)
136 try_return( ntStatus);
139 ntStatus = STATUS_SUCCESS;
142 // Now our IO Worker queue
145 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
148 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
149 sizeof( AFSWorkQueueContext),
152 if( pCurrentWorker == NULL)
155 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
156 AFS_TRACE_LEVEL_ERROR,
157 "AFSInitializeWorkerPool Failed to allocate IO worker context\n");
159 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
164 RtlZeroMemory( pCurrentWorker,
165 sizeof( AFSWorkQueueContext));
167 ntStatus = AFSInitWorkerThread( pCurrentWorker,
168 (PKSTART_ROUTINE)AFSIOWorkerThread);
170 if( !NT_SUCCESS( ntStatus))
173 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
174 AFS_TRACE_LEVEL_ERROR,
175 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n", ntStatus);
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 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
683 AFS_TRACE_LEVEL_ERROR,
684 "AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
686 ntStatus = STATUS_SUCCESS;
691 pWorkItem = AFSRemoveWorkItem();
693 if( pWorkItem == NULL)
696 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
708 // Switch on the type of work item to process
711 switch( pWorkItem->RequestType)
714 case AFS_WORK_FLUSH_FCB:
717 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
718 &pWorkItem->AuthGroup);
720 if( !NT_SUCCESS( ntStatus))
723 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
724 &pWorkItem->AuthGroup,
728 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
730 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
735 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
738 AFSEnumerateGlobalRoot( NULL);
743 case AFS_WORK_INVALIDATE_OBJECT:
746 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
747 pWorkItem->Specific.Invalidate.InvalidateReason);
754 case AFS_WORK_START_IOS:
764 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
765 AFS_TRACE_LEVEL_ERROR,
766 "AFSWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
774 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
777 ntStatus = STATUS_SUCCESS;
780 } // worker thread loop
782 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
784 // Wake up another worker so they too can exit
786 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
790 PsTerminateSystemThread( 0);
796 AFSIOWorkerThread( IN PVOID Context)
799 NTSTATUS ntStatus = STATUS_SUCCESS;
800 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
801 AFSWorkItem *pWorkItem;
802 BOOLEAN freeWorkItem = TRUE;
803 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
805 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
808 // Indicate that we are initialized and ready
811 KeSetEvent( &pPoolContext->WorkerThreadReady,
817 // Indicate we are initialized
820 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
822 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
828 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
831 if( !NT_SUCCESS( ntStatus))
834 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
835 AFS_TRACE_LEVEL_ERROR,
836 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
838 ntStatus = STATUS_SUCCESS;
843 pWorkItem = AFSRemoveIOWorkItem();
845 if( pWorkItem == NULL)
848 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
860 // Switch on the type of work item to process
863 switch( pWorkItem->RequestType)
866 case AFS_WORK_START_IOS:
869 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
872 // The final status is in the gather io
875 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
876 pWorkItem->Specific.CacheAccess.FunctionCode,
877 pWorkItem->Specific.CacheAccess.RequestFlags,
878 pWorkItem->Specific.CacheAccess.IoRuns,
879 pWorkItem->Specific.CacheAccess.RunCount,
880 pWorkItem->Specific.CacheAccess.GatherIo);
883 // Regardless of the status we we do the complete - there may
885 // Decrement the count - setting the event if we were told
886 // to. This may trigger completion.
889 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
896 case AFS_WORK_DEFERRED_WRITE:
899 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
900 pWorkItem->Specific.AsynchIo.Irp,
901 pWorkItem->Specific.AsynchIo.CallingProcess,
911 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
912 AFS_TRACE_LEVEL_ERROR,
913 "AFSIOWorkerThread Unknown request type %d\n", pWorkItem->RequestType);
921 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
924 ntStatus = STATUS_SUCCESS;
927 } // worker thread loop
929 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
931 // Wake up another IOWorker so they too can exit
933 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
937 PsTerminateSystemThread( 0);
943 AFSExamineDirectory( IN AFSObjectInfoCB * pCurrentObject,
944 IN AFSDirectoryCB * pCurrentDirEntry)
948 AFSObjectInfoCB *pCurrentChildObject = NULL;
949 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
950 BOOLEAN bFcbBusy = FALSE;
953 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
955 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
956 AFS_TRACE_LEVEL_VERBOSE,
957 "AFSExamineDirectory Deleting DE %wZ Object %p\n",
958 &pCurrentDirEntry->NameInformation.FileName,
959 pCurrentChildObject);
961 AFSDeleteDirEntry( pCurrentObject,
965 // Acquire ObjectInfoLock shared here so as not to deadlock
966 // with an invalidation call from the service during AFSCleanupFcb
969 lCount = AFSObjectInfoIncrement( pCurrentChildObject,
970 AFS_OBJECT_REFERENCE_WORKER);
972 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
973 AFS_TRACE_LEVEL_VERBOSE,
974 "AFSExamineDirectory Increment count on object %p Cnt %d\n",
979 pCurrentChildObject->Fcb != NULL &&
980 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
984 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
985 // across an AFSCleanupFcb call since it can deadlock with an
986 // invalidation call from the service.
989 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
992 // Cannot hold a TreeLock across an AFSCleanupFcb call
993 // as it can deadlock with an invalidation ioctl initiated
996 // Dropping the TreeLock permits the
997 // pCurrentObject->ObjectReferenceCount to change
1000 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1003 if ( ntStatus == STATUS_RETRY)
1009 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1013 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1016 lCount = AFSObjectInfoDecrement( pCurrentChildObject,
1017 AFS_OBJECT_REFERENCE_WORKER);
1019 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1020 AFS_TRACE_LEVEL_VERBOSE,
1021 "AFSExamineDirectory Decrement1 count on object %p Cnt %d\n",
1022 pCurrentChildObject,
1026 pCurrentChildObject->Fcb != NULL &&
1027 pCurrentChildObject->Fcb->OpenReferenceCount == 0)
1030 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1032 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1033 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1036 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1039 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1041 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1043 AFSDeleteObjectInfo( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1045 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1047 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1049 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1050 AFS_TRACE_LEVEL_VERBOSE,
1051 "AFSExamineDirectory (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1052 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB);
1054 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1057 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1059 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1060 AFS_TRACE_LEVEL_VERBOSE,
1061 "AFSExamineDirectory Deleting object %p\n",
1062 pCurrentChildObject);
1064 AFSDeleteObjectInfo( &pCurrentChildObject);
1069 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1076 // Called with VolumeCB->ObjectInfoTree.TreeLock held shared.
1077 // The TreeLock will be released unless *pbReleaseVolumeLock is set to FALSE.
1081 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
1082 IN BOOLEAN bVolumeObject,
1083 IN OUT BOOLEAN * pbReleaseVolumeLock)
1085 NTSTATUS ntStatus = STATUS_SUCCESS;
1086 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1087 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1088 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
1089 AFSObjectInfoCB *pCurrentChildObject = NULL;
1090 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
1091 LARGE_INTEGER liCurrentTime;
1092 BOOLEAN bFcbBusy = FALSE;
1096 switch ( pCurrentObject->FileType) {
1098 case AFS_FILE_TYPE_DIRECTORY:
1101 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1108 // If this object is deleted then remove it from the parent, if we can
1111 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1112 pCurrentObject->ObjectReferenceCount <= 0 &&
1113 ( pCurrentObject->Fcb == NULL ||
1114 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1115 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1116 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1119 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1122 // Dropping the TreeLock permits the
1123 // pCurrentObject->ObjectReferenceCount to change
1126 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1130 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1133 if ( pCurrentObject->ObjectReferenceCount <= 0)
1136 AFSRemoveFcb( &pCurrentObject->Fcb);
1138 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1141 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1144 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1146 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1148 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1150 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1152 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1154 AFSDbgLogMsg( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1155 AFS_TRACE_LEVEL_VERBOSE,
1156 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1157 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB);
1159 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1162 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1164 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1165 AFS_TRACE_LEVEL_VERBOSE,
1166 "AFSExamineObjectInfo Deleting deleted object %p\n",
1169 AFSDeleteObjectInfo( &pCurrentObject);
1174 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1177 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1182 *pbReleaseVolumeLock = FALSE;
1188 if ( pCurrentObject->Fcb != NULL &&
1189 pCurrentObject->Fcb->CcbListHead != NULL)
1194 for ( pCcb = pCurrentObject->Fcb->CcbListHead;
1196 pCcb = (AFSCcb *)pCcb->ListEntry.fLink)
1199 if ( pCcb->NameArray) {
1201 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1202 AFS_TRACE_LEVEL_VERBOSE,
1203 "AFSExamineObjectInfo Found Object %p Fcb %p Ccb %p\n",
1205 pCurrentObject->Fcb,
1213 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1214 ( pCurrentObject->Fcb != NULL &&
1215 pCurrentObject->Fcb->OpenReferenceCount > 0))
1221 if ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
1222 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1225 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1232 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1235 // Directory Entry Processing
1238 KeQueryTickCount( &liCurrentTime);
1240 while( pCurrentDirEntry != NULL)
1243 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1249 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1255 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1256 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1262 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1263 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1264 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1270 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1273 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1279 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1286 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1289 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1290 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1297 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1300 if( pCurrentDirEntry != NULL)
1303 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1308 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1310 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1313 // Now acquire the locks excl without deadlocking
1316 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1320 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1324 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1326 *pbReleaseVolumeLock = FALSE;
1331 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1334 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1336 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1341 KeQueryTickCount( &liCurrentTime);
1343 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1345 while( pCurrentDirEntry != NULL)
1348 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1354 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1360 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1361 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1367 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1368 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1369 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1375 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1378 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1384 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1391 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1394 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1395 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1402 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1405 if( pCurrentDirEntry != NULL)
1408 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1410 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1415 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1417 while( pCurrentDirEntry != NULL)
1420 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1422 AFSExamineDirectory( pCurrentObject,
1425 pCurrentDirEntry = pNextDirEntry;
1429 // Clear our enumerated flag on this object so we retrieve info again on next access
1432 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1434 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1436 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1442 // Try to grab the volume lock again ... no problem if we don't
1445 if( !AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1449 *pbReleaseVolumeLock = FALSE;
1455 else if ( bVolumeObject == FALSE)
1461 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1463 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1467 *pbReleaseVolumeLock = FALSE;
1472 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1475 KeQueryTickCount( &liCurrentTime);
1477 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1478 ( pCurrentObject->Fcb == NULL ||
1479 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1480 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1481 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1482 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1485 AFSRemoveFcb( &pCurrentObject->Fcb);
1487 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1489 AFSDeleteObjectInfo( &pCurrentObject);
1494 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1497 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1502 case AFS_FILE_TYPE_FILE:
1505 lCount = AFSObjectInfoIncrement( pCurrentObject,
1506 AFS_OBJECT_REFERENCE_WORKER);
1508 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1509 AFS_TRACE_LEVEL_VERBOSE,
1510 "AFSExamineObjectInfo Increment3 count on object %p Cnt %d\n",
1514 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1516 if( pCurrentObject->Fcb != NULL)
1520 // Dropping the TreeLock permits the
1521 // pCurrentObject->ObjectReferenceCount to change
1524 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1527 if ( ntStatus == STATUS_RETRY)
1534 bTemp = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1537 lCount = AFSObjectInfoDecrement( pCurrentObject,
1538 AFS_OBJECT_REFERENCE_WORKER);
1540 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1541 AFS_TRACE_LEVEL_VERBOSE,
1542 "AFSExamineObjectInfo Decrement3 count on object %p Cnt %d\n",
1547 if ( bTemp == FALSE)
1550 *pbReleaseVolumeLock = FALSE;
1555 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1558 KeQueryTickCount( &liCurrentTime);
1560 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1561 ( pCurrentObject->Fcb == NULL ||
1562 ( pCurrentObject->Fcb->OpenReferenceCount <= 0 &&
1563 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount <= 0)) &&
1564 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1565 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1566 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1569 AFSRemoveFcb( &pCurrentObject->Fcb);
1571 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1573 AFSDeleteObjectInfo( &pCurrentObject);
1578 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1581 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1588 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1590 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1594 *pbReleaseVolumeLock = FALSE;
1599 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1602 KeQueryTickCount( &liCurrentTime);
1604 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1605 ( pCurrentObject->Fcb == NULL ||
1606 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1607 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1608 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1609 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1612 AFSRemoveFcb( &pCurrentObject->Fcb);
1614 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1616 AFSDeleteObjectInfo( &pCurrentObject);
1621 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1624 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1633 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1635 NTSTATUS ntStatus = STATUS_SUCCESS;
1636 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1637 BOOLEAN bReleaseVolumeLock = FALSE;
1638 BOOLEAN bVolumeObject = FALSE;
1639 BOOLEAN bFcbBusy = FALSE;
1642 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1646 bReleaseVolumeLock = TRUE;
1648 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1652 while( pCurrentObject != NULL)
1655 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1658 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1661 // If the end of the VolumeCB ObjectInfo List is reached, then
1662 // the next ObjectInformationCB to examine is the one embedded within
1663 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1665 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1666 // is being examined.
1669 if( pNextObject == NULL &&
1670 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1673 pNextObject = &pVolumeCB->ObjectInformation;
1676 bVolumeObject = FALSE;
1681 lCount = AFSObjectInfoIncrement( pNextObject,
1682 AFS_OBJECT_REFERENCE_WORKER);
1684 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1685 AFS_TRACE_LEVEL_VERBOSE,
1686 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1696 bVolumeObject = TRUE;
1699 bFcbBusy = AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeLock);
1704 lCount = AFSObjectInfoDecrement( pNextObject,
1705 AFS_OBJECT_REFERENCE_WORKER);
1707 AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1708 AFS_TRACE_LEVEL_VERBOSE,
1709 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1715 // If AFSExamineObjectInfo drops the VolumeLock before returning
1716 // we must halt processing of the Volume's ObjectInfo list.
1719 if ( bReleaseVolumeLock == FALSE)
1725 pCurrentObject = pNextObject;
1728 if( bReleaseVolumeLock)
1731 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1739 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1742 UNREFERENCED_PARAMETER(Context);
1743 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1744 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1745 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1746 LARGE_INTEGER DueTime;
1749 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1750 BOOLEAN bFcbBusy = FALSE;
1753 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1754 AFS_TRACE_LEVEL_VERBOSE,
1755 "AFSPrimaryVolumeWorkerThread Initialized\n");
1758 // Initialize the timer for the worker thread
1761 DueTime.QuadPart = -(5000);
1765 KeInitializeTimerEx( &Timer,
1766 SynchronizationTimer);
1768 KeSetTimerEx( &Timer,
1774 // Indicate that we are initialized and ready
1777 KeSetEvent( &pPoolContext->WorkerThreadReady,
1782 // Indicate we are initialized
1785 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1787 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1790 if ( bFcbBusy == FALSE)
1793 KeWaitForSingleObject( &Timer,
1806 // This is the primary volume worker so it will traverse the volume list
1807 // looking for cleanup or volumes requiring private workers
1810 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1813 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1815 while( pVolumeCB != NULL)
1818 if( pVolumeCB == AFSGlobalRoot ||
1819 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1823 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1828 if( pVolumeCB->ObjectInfoListHead == NULL)
1831 AFSReleaseResource( pVolumeCB->VolumeLock);
1833 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1835 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1838 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1841 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1845 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1847 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1849 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1854 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1856 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1860 // If VolumeCB is idle, the Volume can be garbage collected
1863 if( pVolumeCB->ObjectInfoListHead == NULL &&
1864 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1865 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1866 pVolumeCB->VolumeReferenceCount == 0 &&
1867 ( pVolumeCB->RootFcb == NULL ||
1868 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1869 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1872 AFSRemoveRootFcb( pVolumeCB);
1874 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1876 AFSRemoveVolume( pVolumeCB);
1881 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1883 AFSReleaseResource( pVolumeCB->VolumeLock);
1886 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1888 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1890 pVolumeCB = pNextVolume;
1896 // Don't need this lock anymore now that we have a volume cb to work with
1899 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1902 // For now we only need the volume lock shared
1905 AFSConvertToShared( pVolumeCB->VolumeLock);
1907 AFSExamineVolume( pVolumeCB);
1913 AFSReleaseResource( pVolumeCB->VolumeLock);
1915 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1918 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1921 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1923 } // worker thread loop
1925 KeCancelTimer( &Timer);
1927 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1929 AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1930 AFS_TRACE_LEVEL_VERBOSE,
1931 "AFSPrimaryVolumeWorkerThread Exiting\n");
1933 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1938 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1943 PsTerminateSystemThread( 0);
1949 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1952 NTSTATUS ntStatus = STATUS_SUCCESS;
1953 AFSDeviceExt *pControlDevExt = NULL;
1956 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1958 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
1959 AFS_TRACE_LEVEL_VERBOSE,
1960 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1961 &pControlDevExt->Specific.Control.QueueLock,
1962 PsGetCurrentThread());
1964 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1967 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1969 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
1970 AFS_TRACE_LEVEL_VERBOSE,
1971 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1975 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1978 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1983 pControlDevExt->Specific.Control.QueueHead = WorkItem;
1986 WorkItem->next = NULL;
1987 pControlDevExt->Specific.Control.QueueTail = WorkItem;
1989 // indicate that the queue has nodes
1990 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
1994 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2000 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
2003 NTSTATUS ntStatus = STATUS_SUCCESS;
2004 AFSDeviceExt *pControlDevExt = NULL;
2007 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2009 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2010 AFS_TRACE_LEVEL_VERBOSE,
2011 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2012 &pControlDevExt->Specific.Control.IOQueueLock,
2013 PsGetCurrentThread());
2015 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2018 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2020 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2021 AFS_TRACE_LEVEL_VERBOSE,
2022 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
2026 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
2029 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
2034 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
2037 WorkItem->next = NULL;
2038 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
2040 // indicate that the queue has nodes
2041 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2045 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2051 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2054 NTSTATUS ntStatus = STATUS_SUCCESS;
2055 AFSDeviceExt *pControlDevExt = NULL;
2058 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2060 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2061 AFS_TRACE_LEVEL_VERBOSE,
2062 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2063 &pControlDevExt->Specific.Control.QueueLock,
2064 PsGetCurrentThread());
2066 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2069 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2071 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2073 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2075 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2076 AFS_TRACE_LEVEL_VERBOSE,
2077 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2082 // indicate that the queue has nodes
2085 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2089 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2098 AFSWorkItem *pWorkItem = NULL;
2099 AFSDeviceExt *pControlDevExt = NULL;
2102 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2104 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2105 AFS_TRACE_LEVEL_VERBOSE,
2106 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2107 &pControlDevExt->Specific.Control.QueueLock,
2108 PsGetCurrentThread());
2110 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2113 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2116 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2118 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2120 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2121 AFS_TRACE_LEVEL_VERBOSE,
2122 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2125 PsGetCurrentThreadId());
2127 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2129 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2132 pControlDevExt->Specific.Control.QueueTail = NULL;
2138 // Wake up another worker
2141 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2147 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2153 AFSRemoveIOWorkItem()
2156 AFSWorkItem *pWorkItem = NULL;
2157 AFSDeviceExt *pControlDevExt = NULL;
2160 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2162 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
2163 AFS_TRACE_LEVEL_VERBOSE,
2164 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2165 &pControlDevExt->Specific.Control.IOQueueLock,
2166 PsGetCurrentThread());
2168 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2171 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2174 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2176 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2178 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2179 AFS_TRACE_LEVEL_VERBOSE,
2180 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2183 PsGetCurrentThreadId());
2185 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2187 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2190 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2196 // Wake up another worker
2199 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2205 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2211 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2214 NTSTATUS ntStatus = STATUS_SUCCESS;
2215 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2218 // Submit the work item to the worker
2221 ntStatus = AFSInsertWorkitem( WorkItem);
2227 // Sync request so block on the work item event
2230 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2241 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2244 NTSTATUS ntStatus = STATUS_SUCCESS;
2245 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2248 // Submit the work item to the worker
2251 ntStatus = AFSInsertIOWorkitem( WorkItem);
2257 // Sync request so block on the work item event
2260 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2271 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2274 NTSTATUS ntStatus = STATUS_SUCCESS;
2275 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2278 // Submit the work item to the worker
2281 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2287 // Sync request so block on the work item event
2290 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2301 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2305 NTSTATUS ntStatus = STATUS_SUCCESS;
2306 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2307 AFSWorkItem *pWorkItem = NULL;
2313 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2314 AFS_TRACE_LEVEL_VERBOSE,
2315 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2316 Fcb->ObjectInformation->FileId.Cell,
2317 Fcb->ObjectInformation->FileId.Volume,
2318 Fcb->ObjectInformation->FileId.Vnode,
2319 Fcb->ObjectInformation->FileId.Unique);
2322 // Increment our flush count here just to keep the number of items in the
2323 // queue down. We'll decrement it just below.
2326 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2331 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2332 AFS_TRACE_LEVEL_VERBOSE,
2333 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2334 Fcb->ObjectInformation->FileId.Cell,
2335 Fcb->ObjectInformation->FileId.Volume,
2336 Fcb->ObjectInformation->FileId.Vnode,
2337 Fcb->ObjectInformation->FileId.Unique);
2339 try_return( ntStatus);
2342 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2345 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2346 AFS_TRACE_LEVEL_ERROR,
2347 "AFSQueueFlushExtents Failing request, in shutdown\n");
2349 try_return( ntStatus = STATUS_TOO_LATE);
2353 // Allocate our request structure and send it to the worker
2356 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2357 sizeof( AFSWorkItem),
2360 if( pWorkItem == NULL)
2363 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2364 AFS_TRACE_LEVEL_ERROR,
2365 "AFSQueueFlushExtents Failed to allocate work item\n");
2367 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2370 RtlZeroMemory( pWorkItem,
2371 sizeof( AFSWorkItem));
2373 pWorkItem->Size = sizeof( AFSWorkItem);
2375 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2377 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2379 if ( AuthGroup == NULL)
2382 RtlZeroMemory( &pWorkItem->AuthGroup,
2385 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2388 &pWorkItem->AuthGroup);
2392 RtlCopyMemory( &pWorkItem->AuthGroup,
2397 pWorkItem->Specific.Fcb.Fcb = Fcb;
2399 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2401 AFSDbgLogMsg( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2402 AFS_TRACE_LEVEL_VERBOSE,
2403 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2407 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2408 AFS_TRACE_LEVEL_VERBOSE,
2409 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2411 Fcb->ObjectInformation->FileId.Cell,
2412 Fcb->ObjectInformation->FileId.Volume,
2413 Fcb->ObjectInformation->FileId.Vnode,
2414 Fcb->ObjectInformation->FileId.Unique);
2416 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2420 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2421 AFS_TRACE_LEVEL_VERBOSE,
2422 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2423 Fcb->ObjectInformation->FileId.Cell,
2424 Fcb->ObjectInformation->FileId.Volume,
2425 Fcb->ObjectInformation->FileId.Vnode,
2426 Fcb->ObjectInformation->FileId.Unique,
2430 // Remove the count we added above
2433 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2435 ASSERT( lCount >= 0);
2440 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2445 if( !NT_SUCCESS( ntStatus))
2448 if( pWorkItem != NULL)
2451 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2453 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2456 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2457 AFS_TRACE_LEVEL_ERROR,
2458 "AFSQueueFlushExtents Failed to queue request Status %08lX\n", ntStatus);
2461 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2466 "EXCEPTION - AFSQueueFlushExtents\n");
2468 AFSDumpTraceFilesFnc();
2475 AFSQueueGlobalRootEnumeration()
2478 NTSTATUS ntStatus = STATUS_SUCCESS;
2479 AFSWorkItem *pWorkItem = NULL;
2484 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2485 sizeof(AFSWorkItem),
2487 if (NULL == pWorkItem)
2490 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2491 AFS_TRACE_LEVEL_ERROR,
2492 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n");
2494 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2497 RtlZeroMemory( pWorkItem,
2498 sizeof(AFSWorkItem));
2500 pWorkItem->Size = sizeof( AFSWorkItem);
2502 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2504 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2505 AFS_TRACE_LEVEL_VERBOSE,
2506 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2509 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2513 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2514 AFS_TRACE_LEVEL_VERBOSE,
2515 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2518 if( !NT_SUCCESS( ntStatus))
2521 if( pWorkItem != NULL)
2524 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2527 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2528 AFS_TRACE_LEVEL_ERROR,
2529 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2533 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2538 "EXCEPTION - AFSQueueGlobalRootEnumeration\n");
2540 AFSDumpTraceFilesFnc();
2547 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2548 IN UCHAR FunctionCode,
2549 IN ULONG RequestFlags,
2550 IN AFSIoRun *IoRuns,
2552 IN AFSGatherIo *GatherIo)
2555 NTSTATUS ntStatus = STATUS_SUCCESS;
2556 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2557 AFSWorkItem *pWorkItem = NULL;
2562 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2565 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2566 AFS_TRACE_LEVEL_ERROR,
2567 "AFSQueueStartIos Failing request, in shutdown\n");
2569 try_return( ntStatus = STATUS_TOO_LATE);
2573 // Allocate our request structure and send it to the worker
2576 pWorkItem = (AFSWorkItem *)AFSLibExAllocatePoolWithTag( NonPagedPool,
2577 sizeof( AFSWorkItem),
2580 if( pWorkItem == NULL)
2583 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2584 AFS_TRACE_LEVEL_ERROR,
2585 "AFSQueueStartIos Failed to allocate work item\n");
2587 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2590 RtlZeroMemory( pWorkItem,
2591 sizeof( AFSWorkItem));
2593 KeInitializeEvent( &pWorkItem->Event,
2597 pWorkItem->Size = sizeof( AFSWorkItem);
2599 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2601 pWorkItem->RequestType = AFS_WORK_START_IOS;
2603 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2605 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2607 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2609 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2611 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2613 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2615 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2616 AFS_TRACE_LEVEL_VERBOSE,
2617 "AFSQueueStartIos Queuing IO Workitem %p\n",
2620 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2624 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2625 AFS_TRACE_LEVEL_VERBOSE,
2626 "AFSQueueStartIos Request complete Status %08lX\n",
2629 if( !NT_SUCCESS( ntStatus))
2632 if( pWorkItem != NULL)
2635 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2639 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2644 "EXCEPTION - AFSQueueStartIos\n");
2646 AFSDumpTraceFilesFnc();
2653 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2654 IN ULONG InvalidateReason)
2657 NTSTATUS ntStatus = STATUS_SUCCESS;
2658 AFSWorkItem *pWorkItem = NULL;
2663 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2664 sizeof(AFSWorkItem),
2666 if (NULL == pWorkItem)
2669 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2670 AFS_TRACE_LEVEL_ERROR,
2671 "AFSQueueInvalidateObject Failed to allocate work item\n");
2673 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2676 RtlZeroMemory( pWorkItem,
2677 sizeof(AFSWorkItem));
2679 pWorkItem->Size = sizeof( AFSWorkItem);
2681 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2683 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2685 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2687 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2688 AFS_TRACE_LEVEL_VERBOSE,
2689 "AFSQueueInvalidateObject Workitem %p\n",
2692 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2696 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2697 AFS_TRACE_LEVEL_VERBOSE,
2698 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2701 if( !NT_SUCCESS( ntStatus))
2704 if( pWorkItem != NULL)
2706 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2709 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2710 AFS_TRACE_LEVEL_ERROR,
2711 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2715 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2720 "EXCEPTION - AFSQueueInvalidateObject\n");
2722 AFSDumpTraceFilesFnc();
2729 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2730 IN PFILE_OBJECT FileObject,
2731 IN HANDLE CallingUser,
2733 IN ULONG BytesToWrite,
2734 IN BOOLEAN bRetrying)
2736 NTSTATUS ntStatus = STATUS_SUCCESS;
2737 AFSWorkItem *pWorkItem = NULL;
2743 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2747 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2750 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2751 AFS_TRACE_LEVEL_ERROR,
2752 "%s Could not pin user memory item\n",
2755 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2758 pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
2759 sizeof(AFSWorkItem),
2762 if (NULL == pWorkItem)
2765 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
2766 AFS_TRACE_LEVEL_ERROR,
2767 "%s Failed to allocate work item\n",
2770 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2773 RtlZeroMemory( pWorkItem,
2774 sizeof(AFSWorkItem));
2776 pWorkItem->Size = sizeof( AFSWorkItem);
2778 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2780 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2782 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2784 pWorkItem->Specific.AsynchIo.Irp = Irp;
2786 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2787 AFS_TRACE_LEVEL_VERBOSE,
2792 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2794 IoMarkIrpPending(Irp);
2796 ntStatus = STATUS_PENDING;
2798 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2803 "EXCEPTION - %s \n",
2806 ntStatus = GetExceptionCode();
2811 AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
2812 AFS_TRACE_LEVEL_VERBOSE,
2813 "%s complete Status %08lX\n",
2817 if( !NT_SUCCESS( ntStatus))
2820 if( pWorkItem != NULL)
2823 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2826 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
2827 AFS_TRACE_LEVEL_ERROR,
2828 "%s Failed to queue request Status %08lX\n",
2838 AFSPostedDeferredWrite( IN PVOID Context1,
2841 UNREFERENCED_PARAMETER( Context2);
2844 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2846 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2847 AFS_TRACE_LEVEL_ERROR,
2852 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2854 if (!NT_SUCCESS( ntStatus))
2857 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2859 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2861 AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2862 AFS_TRACE_LEVEL_ERROR,
2863 "%s (%p) Failed to queue request Status %08lX\n",
2865 pWorkItem->Specific.AsynchIo.Irp,