2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011, 2012, 2013 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
16 * nor the names of their contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission from Kernel Drivers, LLC and Your File System, Inc.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // File: AFSWorker.cpp
37 #include "AFSCommon.h"
41 AFSPostedDeferredWrite( IN PVOID Context1,
45 // Function: AFSInitializeWorkerPool
49 // This function initializes the worker thread pool
53 // A status is returned for the function
57 AFSInitializeWorkerPool()
60 NTSTATUS ntStatus = STATUS_SUCCESS;
61 AFSWorkQueueContext *pCurrentWorker = NULL, *pLastWorker = NULL;
62 AFSDeviceExt *pDevExt = NULL;
67 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
70 // Initialize the worker threads.
73 while( pDevExt->Specific.Library.WorkerCount < AFS_WORKER_COUNT)
76 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
77 sizeof( AFSWorkQueueContext),
80 if( pCurrentWorker == NULL)
83 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
84 AFS_TRACE_LEVEL_ERROR,
85 "AFSInitializeWorkerPool Failed to allocate worker context\n"));
87 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
92 RtlZeroMemory( pCurrentWorker,
93 sizeof( AFSWorkQueueContext));
95 ntStatus = AFSInitWorkerThread( pCurrentWorker,
96 (PKSTART_ROUTINE)AFSWorkerThread);
98 if( !NT_SUCCESS( ntStatus))
101 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
102 AFS_TRACE_LEVEL_ERROR,
103 "AFSInitializeWorkerPool Failed to initialize worker thread Status %08lX\n",
106 ExFreePool( pCurrentWorker);
111 if( pDevExt->Specific.Library.PoolHead == NULL)
114 pDevExt->Specific.Library.PoolHead = pCurrentWorker;
119 pLastWorker->fLink = pCurrentWorker;
122 pLastWorker = pCurrentWorker;
124 pDevExt->Specific.Library.WorkerCount++;
128 // If there was a failure but there is at least one worker, then go with it.
131 if( !NT_SUCCESS( ntStatus) &&
132 pDevExt->Specific.Library.WorkerCount == 0)
135 try_return( ntStatus);
138 ntStatus = STATUS_SUCCESS;
141 // Now our IO Worker queue
144 while( pDevExt->Specific.Library.IOWorkerCount < AFS_IO_WORKER_COUNT)
147 pCurrentWorker = (AFSWorkQueueContext *)AFSLibExAllocatePoolWithTag( NonPagedPool,
148 sizeof( AFSWorkQueueContext),
151 if( pCurrentWorker == NULL)
154 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
155 AFS_TRACE_LEVEL_ERROR,
156 "AFSInitializeWorkerPool Failed to allocate IO worker context\n"));
158 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
163 RtlZeroMemory( pCurrentWorker,
164 sizeof( AFSWorkQueueContext));
166 ntStatus = AFSInitWorkerThread( pCurrentWorker,
167 (PKSTART_ROUTINE)AFSIOWorkerThread);
169 if( !NT_SUCCESS( ntStatus))
172 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
173 AFS_TRACE_LEVEL_ERROR,
174 "AFSInitializeWorkerPool Failed to initialize IO worker thread Status %08lX\n",
177 ExFreePool( pCurrentWorker);
182 if( pDevExt->Specific.Library.IOPoolHead == NULL)
185 pDevExt->Specific.Library.IOPoolHead = pCurrentWorker;
190 pLastWorker->fLink = pCurrentWorker;
193 pLastWorker = pCurrentWorker;
195 pDevExt->Specific.Library.IOWorkerCount++;
199 // If there was a failure but there is at least one worker, then go with it.
202 if( !NT_SUCCESS( ntStatus) &&
203 pDevExt->Specific.Library.IOWorkerCount == 0)
206 try_return( ntStatus);
211 if( !NT_SUCCESS( ntStatus))
215 // Failed to initialize the pool so tear it down
218 AFSRemoveWorkerPool();
226 // Function: AFSRemoveWorkerPool
230 // This function tears down the worker thread pool
234 // A status is returned for the function
238 AFSRemoveWorkerPool()
241 NTSTATUS ntStatus = STATUS_SUCCESS;
243 AFSWorkQueueContext *pCurrentWorker = NULL, *pNextWorker = NULL;
244 AFSDeviceExt *pDevExt = NULL;
246 pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
249 // Loop through the workers shutting them down in two stages.
250 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
251 // stop processing requests. Second, call AFSShutdownWorkerThread()
252 // to wake the workers and wait for them to exit.
255 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
257 while( index < pDevExt->Specific.Library.WorkerCount)
260 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
262 pCurrentWorker = pCurrentWorker->fLink;
264 if ( pCurrentWorker == NULL)
273 pCurrentWorker = pDevExt->Specific.Library.PoolHead;
277 while( index < pDevExt->Specific.Library.WorkerCount)
280 ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
282 pNextWorker = pCurrentWorker->fLink;
284 ExFreePool( pCurrentWorker);
286 pCurrentWorker = pNextWorker;
288 if( pCurrentWorker == NULL)
297 pDevExt->Specific.Library.PoolHead = NULL;
300 // Loop through the IO workers shutting them down in two stages.
301 // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
302 // stop processing requests. Second, call AFSShutdownIOWorkerThread()
303 // to wake the workers and wait for them to exit.
306 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
310 while( index < pDevExt->Specific.Library.IOWorkerCount)
313 ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
315 pCurrentWorker = pCurrentWorker->fLink;
317 if ( pCurrentWorker == NULL)
326 pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
330 while( index < pDevExt->Specific.Library.IOWorkerCount)
333 ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
335 pNextWorker = pCurrentWorker->fLink;
337 ExFreePool( pCurrentWorker);
339 pCurrentWorker = pNextWorker;
341 if( pCurrentWorker == NULL)
350 pDevExt->Specific.Library.IOPoolHead = NULL;
356 AFSInitVolumeWorker( IN AFSVolumeCB *VolumeCB)
359 NTSTATUS ntStatus = STATUS_SUCCESS;
360 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
362 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
363 PKSTART_ROUTINE pStartRoutine = NULL;
369 if ( VolumeCB != AFSGlobalRoot)
372 return STATUS_INVALID_PARAMETER;
375 pStartRoutine = AFSPrimaryVolumeWorkerThread;
378 // Initialize the worker thread
381 KeInitializeEvent( &pWorker->WorkerThreadReady,
386 // Set the worker to process requests
389 pWorker->State = AFS_WORKER_PROCESS_REQUESTS;
395 ntStatus = PsCreateSystemThread( &hThread,
403 if( NT_SUCCESS( ntStatus))
406 ObReferenceObjectByHandle( hThread,
407 GENERIC_READ | GENERIC_WRITE,
410 (PVOID *)&pWorker->WorkerThreadObject,
413 ntStatus = KeWaitForSingleObject( &pWorker->WorkerThreadReady,
419 lCount = InterlockedIncrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
424 KeClearEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent);
435 // Function: AFSInitWorkerThread
439 // This function initializes a worker thread in the pool
443 // A status is returned for the function
447 AFSInitWorkerThread( IN AFSWorkQueueContext *PoolContext,
448 IN PKSTART_ROUTINE WorkerRoutine)
451 NTSTATUS ntStatus = STATUS_SUCCESS;
455 // INitialize the worker signal thread
458 KeInitializeEvent( &PoolContext->WorkerThreadReady,
463 // Set the worker to process requests
466 PoolContext->State = AFS_WORKER_PROCESS_REQUESTS;
472 ntStatus = PsCreateSystemThread( &Handle,
478 (void *)PoolContext);
480 if( NT_SUCCESS( ntStatus))
483 ObReferenceObjectByHandle( Handle,
484 GENERIC_READ | GENERIC_WRITE,
487 (PVOID *)&PoolContext->WorkerThreadObject,
490 ntStatus = KeWaitForSingleObject( &PoolContext->WorkerThreadReady,
503 AFSShutdownVolumeWorker( IN AFSVolumeCB *VolumeCB)
506 NTSTATUS ntStatus = STATUS_SUCCESS;
507 AFSWorkQueueContext *pWorker = &VolumeCB->NonPagedVcb->VolumeWorkerContext;
510 // Clear the 'keep processing' flag
513 ClearFlag( pWorker->State, AFS_WORKER_PROCESS_REQUESTS);
515 if( pWorker->WorkerThreadObject != NULL)
517 while ( BooleanFlagOn( pWorker->State, AFS_WORKER_INITIALIZED) )
520 ntStatus = KeWaitForSingleObject( pWorker->WorkerThreadObject,
527 ObDereferenceObject( pWorker->WorkerThreadObject);
529 pWorker->WorkerThreadObject = NULL;
536 // Function: AFSShutdownWorkerThread
540 // This function shutsdown a worker thread in the pool
544 // A status is returned for the function
548 AFSShutdownWorkerThread( IN AFSWorkQueueContext *PoolContext)
551 NTSTATUS ntStatus = STATUS_SUCCESS;
552 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
554 if( PoolContext->WorkerThreadObject != NULL)
557 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
561 // Wake up the thread if it is a sleep
564 KeSetEvent( &pControlDeviceExt->Specific.Control.WorkerQueueHasItems,
568 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
575 ObDereferenceObject( PoolContext->WorkerThreadObject);
577 PoolContext->WorkerThreadObject = NULL;
584 // Function: AFSShutdownIOWorkerThread
588 // This function shutsdown an IO worker thread in the pool
592 // A status is returned for the function
596 AFSShutdownIOWorkerThread( IN AFSWorkQueueContext *PoolContext)
599 NTSTATUS ntStatus = STATUS_SUCCESS;
600 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
602 if( PoolContext->WorkerThreadObject != NULL)
605 while ( BooleanFlagOn( PoolContext->State, AFS_WORKER_INITIALIZED) )
609 // Wake up the thread if it is a sleep
612 KeSetEvent( &pControlDeviceExt->Specific.Control.IOWorkerQueueHasItems,
616 ntStatus = KeWaitForSingleObject( PoolContext->WorkerThreadObject,
623 ObDereferenceObject( PoolContext->WorkerThreadObject);
625 PoolContext->WorkerThreadObject = NULL;
632 // Function: AFSWorkerThread
636 // This is the worker thread entry point.
640 // A status is returned for the function
644 AFSWorkerThread( IN PVOID Context)
647 NTSTATUS ntStatus = STATUS_SUCCESS;
648 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
649 AFSWorkItem *pWorkItem;
650 BOOLEAN freeWorkItem = TRUE;
651 AFSDeviceExt *pControlDevExt = NULL;
654 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
657 // Indicate that we are initialized and ready
660 KeSetEvent( &pPoolContext->WorkerThreadReady,
665 // Indicate we are initialized
668 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
670 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
676 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
679 if( !NT_SUCCESS( ntStatus))
682 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
683 AFS_TRACE_LEVEL_ERROR,
684 "AFSWorkerThread Wait for queue items failed Status %08lX\n",
687 ntStatus = STATUS_SUCCESS;
692 pWorkItem = AFSRemoveWorkItem();
694 if( pWorkItem == NULL)
697 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
709 // Switch on the type of work item to process
712 switch( pWorkItem->RequestType)
715 case AFS_WORK_FLUSH_FCB:
718 ntStatus = AFSFlushExtents( pWorkItem->Specific.Fcb.Fcb,
719 &pWorkItem->AuthGroup);
721 if( !NT_SUCCESS( ntStatus))
724 AFSReleaseExtentsWithFlush( pWorkItem->Specific.Fcb.Fcb,
725 &pWorkItem->AuthGroup,
729 ASSERT( pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount != 0);
731 lCount = InterlockedDecrement( &pWorkItem->Specific.Fcb.Fcb->OpenReferenceCount);
736 case AFS_WORK_ENUMERATE_GLOBAL_ROOT:
739 AFSEnumerateGlobalRoot( NULL);
744 case AFS_WORK_INVALIDATE_OBJECT:
747 AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
748 pWorkItem->Specific.Invalidate.InvalidateReason);
755 case AFS_WORK_START_IOS:
765 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
766 AFS_TRACE_LEVEL_ERROR,
767 "AFSWorkerThread Unknown request type %d\n",
768 pWorkItem->RequestType));
776 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
779 ntStatus = STATUS_SUCCESS;
782 } // worker thread loop
784 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
786 // Wake up another worker so they too can exit
788 KeSetEvent( &pControlDevExt->Specific.Control.WorkerQueueHasItems,
792 PsTerminateSystemThread( 0);
798 AFSIOWorkerThread( IN PVOID Context)
801 NTSTATUS ntStatus = STATUS_SUCCESS;
802 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
803 AFSWorkItem *pWorkItem;
804 BOOLEAN freeWorkItem = TRUE;
805 AFSDeviceExt *pControlDevExt = NULL, *pRdrDevExt = NULL;
807 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
810 // Indicate that we are initialized and ready
813 KeSetEvent( &pPoolContext->WorkerThreadReady,
819 // Indicate we are initialized
822 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
824 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
830 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
833 if( !NT_SUCCESS( ntStatus))
836 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
837 AFS_TRACE_LEVEL_ERROR,
838 "AFSIOWorkerThread Wait for queue items failed Status %08lX\n",
841 ntStatus = STATUS_SUCCESS;
846 pWorkItem = AFSRemoveIOWorkItem();
848 if( pWorkItem == NULL)
851 ntStatus = KeWaitForSingleObject( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
863 // Switch on the type of work item to process
866 switch( pWorkItem->RequestType)
869 case AFS_WORK_START_IOS:
872 pRdrDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
875 // The final status is in the gather io
878 ntStatus = AFSStartIos( pWorkItem->Specific.CacheAccess.CacheFileObject,
879 pWorkItem->Specific.CacheAccess.FunctionCode,
880 pWorkItem->Specific.CacheAccess.RequestFlags,
881 pWorkItem->Specific.CacheAccess.IoRuns,
882 pWorkItem->Specific.CacheAccess.RunCount,
883 pWorkItem->Specific.CacheAccess.GatherIo);
886 // Regardless of the status we we do the complete - there may
888 // Decrement the count - setting the event if we were told
889 // to. This may trigger completion.
892 AFSCompleteIo( pWorkItem->Specific.CacheAccess.GatherIo, ntStatus );
899 case AFS_WORK_DEFERRED_WRITE:
902 ntStatus = AFSCommonWrite( pWorkItem->Specific.AsynchIo.Device,
903 pWorkItem->Specific.AsynchIo.Irp,
904 pWorkItem->Specific.AsynchIo.CallingProcess,
914 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
915 AFS_TRACE_LEVEL_ERROR,
916 "AFSIOWorkerThread Unknown request type %d\n",
917 pWorkItem->RequestType));
925 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
928 ntStatus = STATUS_SUCCESS;
931 } // worker thread loop
933 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
935 // Wake up another IOWorker so they too can exit
937 KeSetEvent( &pControlDevExt->Specific.Control.IOWorkerQueueHasItems,
941 PsTerminateSystemThread( 0);
947 AFSExamineDirectory( IN AFSObjectInfoCB * pCurrentObject,
948 IN AFSDirectoryCB * pCurrentDirEntry)
952 AFSObjectInfoCB *pCurrentChildObject = NULL;
953 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
954 BOOLEAN bFcbBusy = FALSE;
957 pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
959 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
960 AFS_TRACE_LEVEL_VERBOSE,
961 "AFSExamineDirectory Deleting DE %wZ Object %p\n",
962 &pCurrentDirEntry->NameInformation.FileName,
963 pCurrentChildObject));
965 AFSDeleteDirEntry( pCurrentObject,
968 if ( pCurrentChildObject != NULL)
972 // Acquire ObjectInfoLock shared here so as not to deadlock
973 // with an invalidation call from the service during AFSCleanupFcb
976 lCount = AFSObjectInfoIncrement( pCurrentChildObject,
977 AFS_OBJECT_REFERENCE_WORKER);
979 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
980 AFS_TRACE_LEVEL_VERBOSE,
981 "AFSExamineDirectory Increment count on object %p Cnt %d\n",
986 pCurrentChildObject->Fcb != NULL &&
987 pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
991 // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
992 // across an AFSCleanupFcb call since it can deadlock with an
993 // invalidation call from the service.
996 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
999 // Cannot hold a TreeLock across an AFSCleanupFcb call
1000 // as it can deadlock with an invalidation ioctl initiated
1001 // from the service.
1003 // Dropping the TreeLock permits the
1004 // pCurrentObject->ObjectReferenceCount to change
1007 ntStatus = AFSCleanupFcb( pCurrentChildObject->Fcb,
1010 if ( ntStatus == STATUS_RETRY)
1016 AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1020 AFSAcquireExcl( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock,
1023 lCount = AFSObjectInfoDecrement( pCurrentChildObject,
1024 AFS_OBJECT_REFERENCE_WORKER);
1026 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1027 AFS_TRACE_LEVEL_VERBOSE,
1028 "AFSExamineDirectory Decrement1 count on object %p Cnt %d\n",
1029 pCurrentChildObject,
1033 pCurrentChildObject->Fcb != NULL &&
1034 pCurrentChildObject->Fcb->OpenReferenceCount == 0)
1037 AFSRemoveFcb( &pCurrentChildObject->Fcb);
1039 if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
1040 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1043 AFSAcquireExcl( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1046 AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1048 AFSReleaseResource( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1050 AFSDeleteObjectInfo( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1052 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1054 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1056 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1057 AFS_TRACE_LEVEL_VERBOSE,
1058 "AFSExamineDirectory (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1059 pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB));
1061 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1064 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1066 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING | AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1067 AFS_TRACE_LEVEL_VERBOSE,
1068 "AFSExamineDirectory Deleting object %p\n",
1069 pCurrentChildObject));
1071 AFSDeleteObjectInfo( &pCurrentChildObject);
1076 AFSReleaseResource( &pCurrentChildObject->NonPagedInfo->ObjectInfoLock);
1084 // Called with VolumeCB->ObjectInfoTree.TreeLock held shared.
1085 // The TreeLock will be released unless *pbReleaseVolumeLock is set to FALSE.
1089 AFSExamineObjectInfo( IN AFSObjectInfoCB * pCurrentObject,
1090 IN BOOLEAN bVolumeObject,
1091 IN OUT BOOLEAN * pbReleaseVolumeLock)
1093 NTSTATUS ntStatus = STATUS_SUCCESS;
1094 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1095 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1096 AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
1097 AFSObjectInfoCB *pCurrentChildObject = NULL;
1098 AFSVolumeCB * pVolumeCB = pCurrentObject->VolumeCB;
1099 LARGE_INTEGER liCurrentTime;
1100 BOOLEAN bFcbBusy = FALSE;
1104 switch ( pCurrentObject->FileType) {
1106 case AFS_FILE_TYPE_DIRECTORY:
1109 if ( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
1116 // If this object is deleted then remove it from the parent, if we can
1119 if( BooleanFlagOn( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DELETED) &&
1120 pCurrentObject->ObjectReferenceCount <= 0 &&
1121 ( pCurrentObject->Fcb == NULL ||
1122 pCurrentObject->Fcb->OpenReferenceCount == 0) &&
1123 pCurrentObject->Specific.Directory.DirectoryNodeListHead == NULL &&
1124 pCurrentObject->Specific.Directory.ChildOpenReferenceCount == 0)
1127 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1130 // Dropping the TreeLock permits the
1131 // pCurrentObject->ObjectReferenceCount to change
1134 if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1138 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1141 if ( pCurrentObject->ObjectReferenceCount <= 0)
1144 AFSRemoveFcb( &pCurrentObject->Fcb);
1146 if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
1149 AFSAcquireExcl( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock,
1152 AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
1154 AFSReleaseResource( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->NonPagedInfo->ObjectInfoLock);
1156 AFSDeleteObjectInfo( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
1158 ExDeleteResourceLite( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged->Lock);
1160 AFSExFreePoolWithTag( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->NonPaged, AFS_DIR_ENTRY_NP_TAG);
1162 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_ALLOCATION,
1163 AFS_TRACE_LEVEL_VERBOSE,
1164 "AFSExamineObjectInfo (pioctl) AFS_DIR_ENTRY_TAG deallocating %p\n",
1165 pCurrentObject->Specific.Directory.PIOCtlDirectoryCB));
1167 AFSExFreePoolWithTag( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB, AFS_DIR_ENTRY_TAG);
1170 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1172 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1173 AFS_TRACE_LEVEL_VERBOSE,
1174 "AFSExamineObjectInfo Deleting deleted object %p\n",
1177 AFSDeleteObjectInfo( &pCurrentObject);
1182 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1185 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1190 *pbReleaseVolumeLock = FALSE;
1196 if ( pCurrentObject->Fcb != NULL &&
1197 pCurrentObject->Fcb->CcbListHead != NULL)
1202 for ( pCcb = pCurrentObject->Fcb->CcbListHead;
1204 pCcb = (AFSCcb *)pCcb->ListEntry.fLink)
1207 if ( pCcb->NameArray) {
1209 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1210 AFS_TRACE_LEVEL_VERBOSE,
1211 "AFSExamineObjectInfo Found Object %p Fcb %p Ccb %p\n",
1213 pCurrentObject->Fcb,
1221 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0 ||
1222 ( pCurrentObject->Fcb != NULL &&
1223 pCurrentObject->Fcb->OpenReferenceCount > 0))
1229 if ( pCurrentObject->FileType != AFS_FILE_TYPE_DIRECTORY ||
1230 pCurrentObject->Specific.Directory.DirectoryNodeListHead != NULL)
1233 if( !AFSAcquireShared( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1240 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1243 // Directory Entry Processing
1246 KeQueryTickCount( &liCurrentTime);
1248 while( pCurrentDirEntry != NULL)
1251 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1257 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1263 if ( pCurrentDirEntry->ObjectInformation != NULL)
1266 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1267 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1273 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1274 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1275 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1281 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1284 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1290 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1297 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1300 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1301 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1309 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1312 if( pCurrentDirEntry != NULL)
1315 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1320 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1322 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1325 // Now acquire the locks excl without deadlocking
1328 if( AFSAcquireExcl( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock,
1332 if( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1336 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1338 *pbReleaseVolumeLock = FALSE;
1343 if( pCurrentObject->Specific.Directory.ChildOpenReferenceCount > 0)
1346 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1348 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1353 KeQueryTickCount( &liCurrentTime);
1355 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1357 while( pCurrentDirEntry != NULL)
1360 if( pCurrentDirEntry->DirOpenReferenceCount > 0)
1366 if ( pCurrentDirEntry->NameArrayReferenceCount > 0)
1372 if ( pCurrentDirEntry->ObjectInformation != NULL)
1375 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1376 pCurrentDirEntry->ObjectInformation->Fcb->OpenReferenceCount > 0)
1382 if ( liCurrentTime.QuadPart <= pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart ||
1383 liCurrentTime.QuadPart - pCurrentDirEntry->ObjectInformation->LastAccessCount.QuadPart <
1384 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1390 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_DIRECTORY)
1393 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.DirectoryNodeListHead != NULL)
1399 if ( pCurrentDirEntry->ObjectInformation->Specific.Directory.ChildOpenReferenceCount > 0)
1406 if ( pCurrentDirEntry->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
1409 if ( pCurrentDirEntry->ObjectInformation->Fcb != NULL &&
1410 pCurrentDirEntry->ObjectInformation->Fcb->Specific.File.ExtentsDirtyCount > 0)
1418 pCurrentDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1421 if( pCurrentDirEntry != NULL)
1424 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1426 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1431 pCurrentDirEntry = pCurrentObject->Specific.Directory.DirectoryNodeListHead;
1433 while( pCurrentDirEntry != NULL)
1436 pNextDirEntry = (AFSDirectoryCB *)pCurrentDirEntry->ListEntry.fLink;
1438 AFSExamineDirectory( pCurrentObject,
1441 pCurrentDirEntry = pNextDirEntry;
1445 // Clear our enumerated flag on this object so we retrieve info again on next access
1448 ClearFlag( pCurrentObject->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
1450 AFSReleaseResource( pCurrentObject->Specific.Directory.DirectoryNodeHdr.TreeLock);
1452 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1458 // Try to grab the volume lock again ... no problem if we don't
1461 if( !AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1465 *pbReleaseVolumeLock = FALSE;
1471 else if ( bVolumeObject == FALSE)
1477 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1479 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1483 *pbReleaseVolumeLock = FALSE;
1488 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1491 KeQueryTickCount( &liCurrentTime);
1493 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1494 ( pCurrentObject->Fcb == NULL ||
1495 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1496 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1497 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1498 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1501 AFSRemoveFcb( &pCurrentObject->Fcb);
1503 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1505 AFSDeleteObjectInfo( &pCurrentObject);
1510 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1513 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1518 case AFS_FILE_TYPE_FILE:
1521 lCount = AFSObjectInfoIncrement( pCurrentObject,
1522 AFS_OBJECT_REFERENCE_WORKER);
1524 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1525 AFS_TRACE_LEVEL_VERBOSE,
1526 "AFSExamineObjectInfo Increment3 count on object %p Cnt %d\n",
1530 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1532 if( pCurrentObject->Fcb != NULL)
1536 // Dropping the TreeLock permits the
1537 // pCurrentObject->ObjectReferenceCount to change
1540 ntStatus = AFSCleanupFcb( pCurrentObject->Fcb,
1543 if ( ntStatus == STATUS_RETRY)
1550 bTemp = AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1553 lCount = AFSObjectInfoDecrement( pCurrentObject,
1554 AFS_OBJECT_REFERENCE_WORKER);
1556 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1557 AFS_TRACE_LEVEL_VERBOSE,
1558 "AFSExamineObjectInfo Decrement3 count on object %p Cnt %d\n",
1562 if ( bTemp == FALSE)
1565 *pbReleaseVolumeLock = FALSE;
1570 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1573 KeQueryTickCount( &liCurrentTime);
1575 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1576 ( pCurrentObject->Fcb == NULL ||
1577 ( pCurrentObject->Fcb->OpenReferenceCount <= 0 &&
1578 pCurrentObject->Fcb->Specific.File.ExtentsDirtyCount <= 0)) &&
1579 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1580 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1581 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1584 AFSRemoveFcb( &pCurrentObject->Fcb);
1586 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1588 AFSDeleteObjectInfo( &pCurrentObject);
1593 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1596 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1603 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1605 if ( !AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
1609 *pbReleaseVolumeLock = FALSE;
1614 AFSAcquireExcl( &pCurrentObject->NonPagedInfo->ObjectInfoLock,
1617 KeQueryTickCount( &liCurrentTime);
1619 if( pCurrentObject->ObjectReferenceCount <= 0 &&
1620 ( pCurrentObject->Fcb == NULL ||
1621 pCurrentObject->Fcb->OpenReferenceCount <= 0) &&
1622 liCurrentTime.QuadPart > pCurrentObject->LastAccessCount.QuadPart &&
1623 liCurrentTime.QuadPart - pCurrentObject->LastAccessCount.QuadPart >
1624 pControlDeviceExt->Specific.Control.ObjectLifeTimeCount.QuadPart)
1627 AFSRemoveFcb( &pCurrentObject->Fcb);
1629 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1631 AFSDeleteObjectInfo( &pCurrentObject);
1636 AFSReleaseResource( &pCurrentObject->NonPagedInfo->ObjectInfoLock);
1639 AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
1648 AFSExamineVolume( IN AFSVolumeCB *pVolumeCB)
1650 NTSTATUS ntStatus = STATUS_SUCCESS;
1651 AFSObjectInfoCB *pCurrentObject = NULL, *pNextObject = NULL;
1652 BOOLEAN bReleaseVolumeLock = FALSE;
1653 BOOLEAN bVolumeObject = FALSE;
1654 BOOLEAN bFcbBusy = FALSE;
1657 if( AFSAcquireShared( pVolumeCB->ObjectInfoTree.TreeLock,
1661 bReleaseVolumeLock = TRUE;
1663 pCurrentObject = pVolumeCB->ObjectInfoListHead;
1667 while( pCurrentObject != NULL)
1670 if( pCurrentObject != &pVolumeCB->ObjectInformation)
1673 pNextObject = (AFSObjectInfoCB *)pCurrentObject->ListEntry.fLink;
1676 // If the end of the VolumeCB ObjectInfo List is reached, then
1677 // the next ObjectInformationCB to examine is the one embedded within
1678 // the VolumeCB itself except when the VolumeCB is the AFSGlobalRoot.
1680 // bVolumeObject is used to indicate whether the embedded ObjectInfoCB
1681 // is being examined.
1684 if( pNextObject == NULL &&
1685 pVolumeCB != AFSGlobalRoot) // Don't free up the root of the global
1688 pNextObject = &pVolumeCB->ObjectInformation;
1691 bVolumeObject = FALSE;
1696 lCount = AFSObjectInfoIncrement( pNextObject,
1697 AFS_OBJECT_REFERENCE_WORKER);
1699 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1700 AFS_TRACE_LEVEL_VERBOSE,
1701 "AFSExamineVolume Increment count on object %p Cnt %d\n",
1711 bVolumeObject = TRUE;
1714 bFcbBusy = AFSExamineObjectInfo( pCurrentObject, bVolumeObject, &bReleaseVolumeLock);
1719 lCount = AFSObjectInfoDecrement( pNextObject,
1720 AFS_OBJECT_REFERENCE_WORKER);
1722 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
1723 AFS_TRACE_LEVEL_VERBOSE,
1724 "AFSExamineVolume Decrement count on object %p Cnt %d\n",
1730 // If AFSExamineObjectInfo drops the VolumeLock before returning
1731 // we must halt processing of the Volume's ObjectInfo list.
1734 if ( bReleaseVolumeLock == FALSE)
1740 pCurrentObject = pNextObject;
1743 if( bReleaseVolumeLock)
1746 AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
1754 AFSPrimaryVolumeWorkerThread( IN PVOID Context)
1757 UNREFERENCED_PARAMETER(Context);
1758 AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->NonPagedVcb->VolumeWorkerContext;
1759 AFSDeviceExt *pControlDeviceExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1760 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
1761 LARGE_INTEGER DueTime;
1764 AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
1765 BOOLEAN bFcbBusy = FALSE;
1768 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1769 AFS_TRACE_LEVEL_VERBOSE,
1770 "AFSPrimaryVolumeWorkerThread Initialized\n"));
1773 // Initialize the timer for the worker thread
1776 DueTime.QuadPart = -(5000);
1780 KeInitializeTimerEx( &Timer,
1781 SynchronizationTimer);
1783 KeSetTimerEx( &Timer,
1789 // Indicate that we are initialized and ready
1792 KeSetEvent( &pPoolContext->WorkerThreadReady,
1797 // Indicate we are initialized
1800 SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1802 while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
1805 if ( bFcbBusy == FALSE)
1808 KeWaitForSingleObject( &Timer,
1821 // This is the primary volume worker so it will traverse the volume list
1822 // looking for cleanup or volumes requiring private workers
1825 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1828 pVolumeCB = pRDRDeviceExt->Specific.RDR.VolumeListHead;
1830 while( pVolumeCB != NULL)
1833 if( pVolumeCB == AFSGlobalRoot ||
1834 !AFSAcquireExcl( pVolumeCB->VolumeLock,
1838 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1843 if( pVolumeCB->ObjectInfoListHead == NULL)
1846 AFSReleaseResource( pVolumeCB->VolumeLock);
1848 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1850 AFSAcquireExcl( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock,
1853 AFSAcquireExcl( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1856 if( !AFSAcquireExcl( pVolumeCB->VolumeLock,
1860 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1862 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1864 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1869 pNextVolume = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1871 AFSAcquireShared( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock,
1875 // If VolumeCB is idle, the Volume can be garbage collected
1878 if( pVolumeCB->ObjectInfoListHead == NULL &&
1879 pVolumeCB->DirectoryCB->DirOpenReferenceCount <= 0 &&
1880 pVolumeCB->DirectoryCB->NameArrayReferenceCount <= 0 &&
1881 pVolumeCB->VolumeReferenceCount == 0 &&
1882 ( pVolumeCB->RootFcb == NULL ||
1883 pVolumeCB->RootFcb->OpenReferenceCount == 0) &&
1884 pVolumeCB->ObjectInformation.ObjectReferenceCount <= 0)
1887 AFSRemoveRootFcb( pVolumeCB);
1889 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1891 AFSRemoveVolume( pVolumeCB);
1896 AFSReleaseResource( &pVolumeCB->ObjectInformation.NonPagedInfo->ObjectInfoLock);
1898 AFSReleaseResource( pVolumeCB->VolumeLock);
1901 AFSConvertToShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1903 AFSReleaseResource( pRDRDeviceExt->Specific.RDR.VolumeTree.TreeLock);
1905 pVolumeCB = pNextVolume;
1911 // Don't need this lock anymore now that we have a volume cb to work with
1914 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1917 // For now we only need the volume lock shared
1920 AFSConvertToShared( pVolumeCB->VolumeLock);
1922 AFSExamineVolume( pVolumeCB);
1928 AFSReleaseResource( pVolumeCB->VolumeLock);
1930 AFSAcquireShared( &pRDRDeviceExt->Specific.RDR.VolumeListLock,
1933 pVolumeCB = (AFSVolumeCB *)pVolumeCB->ListEntry.fLink;
1936 AFSReleaseResource( &pRDRDeviceExt->Specific.RDR.VolumeListLock);
1938 } // worker thread loop
1940 KeCancelTimer( &Timer);
1942 ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
1944 AFSDbgTrace(( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
1945 AFS_TRACE_LEVEL_VERBOSE,
1946 "AFSPrimaryVolumeWorkerThread Exiting\n"));
1948 lCount = InterlockedDecrement( &pControlDeviceExt->Specific.Control.VolumeWorkerThreadCount);
1953 KeSetEvent( &pControlDeviceExt->Specific.Control.VolumeWorkerCloseEvent,
1958 PsTerminateSystemThread( 0);
1964 AFSInsertWorkitem( IN AFSWorkItem *WorkItem)
1967 NTSTATUS ntStatus = STATUS_SUCCESS;
1968 AFSDeviceExt *pControlDevExt = NULL;
1971 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
1973 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
1974 AFS_TRACE_LEVEL_VERBOSE,
1975 "AFSInsertWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
1976 &pControlDevExt->Specific.Control.QueueLock,
1977 PsGetCurrentThread()));
1979 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
1982 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
1984 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
1985 AFS_TRACE_LEVEL_VERBOSE,
1986 "AFSInsertWorkitem Inserting work item %p Count %d\n",
1990 if( pControlDevExt->Specific.Control.QueueTail != NULL) // queue already has nodes
1993 pControlDevExt->Specific.Control.QueueTail->next = WorkItem;
1998 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2001 WorkItem->next = NULL;
2002 pControlDevExt->Specific.Control.QueueTail = WorkItem;
2004 // indicate that the queue has nodes
2005 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2009 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2015 AFSInsertIOWorkitem( IN AFSWorkItem *WorkItem)
2018 NTSTATUS ntStatus = STATUS_SUCCESS;
2019 AFSDeviceExt *pControlDevExt = NULL;
2022 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2024 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2025 AFS_TRACE_LEVEL_VERBOSE,
2026 "AFSInsertIOWorkitem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2027 &pControlDevExt->Specific.Control.IOQueueLock,
2028 PsGetCurrentThread()));
2030 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2033 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2035 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2036 AFS_TRACE_LEVEL_VERBOSE,
2037 "AFSInsertWorkitem Inserting IO work item %p Count %d\n",
2041 if( pControlDevExt->Specific.Control.IOQueueTail != NULL) // queue already has nodes
2044 pControlDevExt->Specific.Control.IOQueueTail->next = WorkItem;
2049 pControlDevExt->Specific.Control.IOQueueHead = WorkItem;
2052 WorkItem->next = NULL;
2053 pControlDevExt->Specific.Control.IOQueueTail = WorkItem;
2055 // indicate that the queue has nodes
2056 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2060 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2066 AFSInsertWorkitemAtHead( IN AFSWorkItem *WorkItem)
2069 NTSTATUS ntStatus = STATUS_SUCCESS;
2070 AFSDeviceExt *pControlDevExt = NULL;
2073 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2075 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2076 AFS_TRACE_LEVEL_VERBOSE,
2077 "AFSInsertWorkitemAtHead Acquiring Control QueueLock lock %p EXCL %08lX\n",
2078 &pControlDevExt->Specific.Control.QueueLock,
2079 PsGetCurrentThread()));
2081 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2084 WorkItem->next = pControlDevExt->Specific.Control.QueueHead;
2086 pControlDevExt->Specific.Control.QueueHead = WorkItem;
2088 lCount = InterlockedIncrement( &pControlDevExt->Specific.Control.QueueItemCount);
2090 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2091 AFS_TRACE_LEVEL_VERBOSE,
2092 "AFSInsertWorkitemAtHead Inserting work item %p Count %d\n",
2097 // indicate that the queue has nodes
2100 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2104 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2113 AFSWorkItem *pWorkItem = NULL;
2114 AFSDeviceExt *pControlDevExt = NULL;
2117 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2119 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2120 AFS_TRACE_LEVEL_VERBOSE,
2121 "AFSRemoveWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2122 &pControlDevExt->Specific.Control.QueueLock,
2123 PsGetCurrentThread()));
2125 AFSAcquireExcl( &pControlDevExt->Specific.Control.QueueLock,
2128 if( pControlDevExt->Specific.Control.QueueHead != NULL) // queue has nodes
2131 pWorkItem = pControlDevExt->Specific.Control.QueueHead;
2133 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.QueueItemCount);
2135 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2136 AFS_TRACE_LEVEL_VERBOSE,
2137 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2140 PsGetCurrentThreadId()));
2142 pControlDevExt->Specific.Control.QueueHead = pControlDevExt->Specific.Control.QueueHead->next;
2144 if( pControlDevExt->Specific.Control.QueueHead == NULL) // if queue just became empty
2147 pControlDevExt->Specific.Control.QueueTail = NULL;
2153 // Wake up another worker
2156 KeSetEvent( &(pControlDevExt->Specific.Control.WorkerQueueHasItems),
2162 AFSReleaseResource( &pControlDevExt->Specific.Control.QueueLock);
2168 AFSRemoveIOWorkItem()
2171 AFSWorkItem *pWorkItem = NULL;
2172 AFSDeviceExt *pControlDevExt = NULL;
2175 pControlDevExt = (AFSDeviceExt *)AFSControlDeviceObject->DeviceExtension;
2177 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING,
2178 AFS_TRACE_LEVEL_VERBOSE,
2179 "AFSRemoveIOWorkItem Acquiring Control QueueLock lock %p EXCL %08lX\n",
2180 &pControlDevExt->Specific.Control.IOQueueLock,
2181 PsGetCurrentThread()));
2183 AFSAcquireExcl( &pControlDevExt->Specific.Control.IOQueueLock,
2186 if( pControlDevExt->Specific.Control.IOQueueHead != NULL) // queue has nodes
2189 pWorkItem = pControlDevExt->Specific.Control.IOQueueHead;
2191 lCount = InterlockedDecrement( &pControlDevExt->Specific.Control.IOQueueItemCount);
2193 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2194 AFS_TRACE_LEVEL_VERBOSE,
2195 "AFSRemoveWorkItem Removing work item %p Count %d Thread %08lX\n",
2198 PsGetCurrentThreadId()));
2200 pControlDevExt->Specific.Control.IOQueueHead = pControlDevExt->Specific.Control.IOQueueHead->next;
2202 if( pControlDevExt->Specific.Control.IOQueueHead == NULL) // if queue just became empty
2205 pControlDevExt->Specific.Control.IOQueueTail = NULL;
2211 // Wake up another worker
2214 KeSetEvent( &(pControlDevExt->Specific.Control.IOWorkerQueueHasItems),
2220 AFSReleaseResource( &pControlDevExt->Specific.Control.IOQueueLock);
2226 AFSQueueWorkerRequest( IN AFSWorkItem *WorkItem)
2229 NTSTATUS ntStatus = STATUS_SUCCESS;
2230 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2233 // Submit the work item to the worker
2236 ntStatus = AFSInsertWorkitem( WorkItem);
2242 // Sync request so block on the work item event
2245 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2256 AFSQueueIOWorkerRequest( IN AFSWorkItem *WorkItem)
2259 NTSTATUS ntStatus = STATUS_SUCCESS;
2260 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2263 // Submit the work item to the worker
2266 ntStatus = AFSInsertIOWorkitem( WorkItem);
2272 // Sync request so block on the work item event
2275 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2286 AFSQueueWorkerRequestAtHead( IN AFSWorkItem *WorkItem)
2289 NTSTATUS ntStatus = STATUS_SUCCESS;
2290 BOOLEAN bWait = BooleanFlagOn( WorkItem->RequestFlags, AFS_SYNCHRONOUS_REQUEST);
2293 // Submit the work item to the worker
2296 ntStatus = AFSInsertWorkitemAtHead( WorkItem);
2302 // Sync request so block on the work item event
2305 ntStatus = KeWaitForSingleObject( &WorkItem->Event,
2316 AFSQueueFlushExtents( IN AFSFcb *Fcb,
2320 NTSTATUS ntStatus = STATUS_SUCCESS;
2321 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2322 AFSWorkItem *pWorkItem = NULL;
2328 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2329 AFS_TRACE_LEVEL_VERBOSE,
2330 "AFSQueueFlushExtents Queuing request for FID %08lX-%08lX-%08lX-%08lX\n",
2331 Fcb->ObjectInformation->FileId.Cell,
2332 Fcb->ObjectInformation->FileId.Volume,
2333 Fcb->ObjectInformation->FileId.Vnode,
2334 Fcb->ObjectInformation->FileId.Unique));
2337 // Increment our flush count here just to keep the number of items in the
2338 // queue down. We'll decrement it just below.
2341 lCount = InterlockedIncrement( &Fcb->Specific.File.QueuedFlushCount);
2346 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2347 AFS_TRACE_LEVEL_VERBOSE,
2348 "AFSQueueFlushExtents Max queued items for FID %08lX-%08lX-%08lX-%08lX\n",
2349 Fcb->ObjectInformation->FileId.Cell,
2350 Fcb->ObjectInformation->FileId.Volume,
2351 Fcb->ObjectInformation->FileId.Vnode,
2352 Fcb->ObjectInformation->FileId.Unique));
2354 try_return( ntStatus);
2357 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2360 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2361 AFS_TRACE_LEVEL_ERROR,
2362 "AFSQueueFlushExtents Failing request, in shutdown\n"));
2364 try_return( ntStatus = STATUS_TOO_LATE);
2368 // Allocate our request structure and send it to the worker
2371 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2372 sizeof( AFSWorkItem),
2375 if( pWorkItem == NULL)
2378 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2379 AFS_TRACE_LEVEL_ERROR,
2380 "AFSQueueFlushExtents Failed to allocate work item\n"));
2382 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2385 RtlZeroMemory( pWorkItem,
2386 sizeof( AFSWorkItem));
2388 pWorkItem->Size = sizeof( AFSWorkItem);
2390 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2392 pWorkItem->RequestType = AFS_WORK_FLUSH_FCB;
2394 if ( AuthGroup == NULL)
2397 RtlZeroMemory( &pWorkItem->AuthGroup,
2400 ntStatus = AFSRetrieveValidAuthGroup( Fcb,
2403 &pWorkItem->AuthGroup);
2407 RtlCopyMemory( &pWorkItem->AuthGroup,
2412 pWorkItem->Specific.Fcb.Fcb = Fcb;
2414 lCount = InterlockedIncrement( &Fcb->OpenReferenceCount);
2416 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2417 AFS_TRACE_LEVEL_VERBOSE,
2418 "AFSQueueFlushExtents Increment count on Fcb %p Cnt %d\n",
2422 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2423 AFS_TRACE_LEVEL_VERBOSE,
2424 "AFSQueueFlushExtents Workitem %p for FID %08lX-%08lX-%08lX-%08lX\n",
2426 Fcb->ObjectInformation->FileId.Cell,
2427 Fcb->ObjectInformation->FileId.Volume,
2428 Fcb->ObjectInformation->FileId.Vnode,
2429 Fcb->ObjectInformation->FileId.Unique));
2431 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2435 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2436 AFS_TRACE_LEVEL_VERBOSE,
2437 "AFSQueueFlushExtents Request complete Status %08lX FID %08lX-%08lX-%08lX-%08lX\n",
2438 Fcb->ObjectInformation->FileId.Cell,
2439 Fcb->ObjectInformation->FileId.Volume,
2440 Fcb->ObjectInformation->FileId.Vnode,
2441 Fcb->ObjectInformation->FileId.Unique,
2445 // Remove the count we added above
2448 lCount = InterlockedDecrement( &Fcb->Specific.File.QueuedFlushCount);
2450 ASSERT( lCount >= 0);
2455 KeSetEvent( &Fcb->NPFcb->Specific.File.QueuedFlushEvent,
2460 if( !NT_SUCCESS( ntStatus))
2463 if( pWorkItem != NULL)
2466 lCount = InterlockedDecrement( &Fcb->OpenReferenceCount);
2468 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2471 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2472 AFS_TRACE_LEVEL_ERROR,
2473 "AFSQueueFlushExtents Failed to queue request Status %08lX\n",
2477 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2482 "EXCEPTION - AFSQueueFlushExtents\n"));
2484 AFSDumpTraceFilesFnc();
2491 AFSQueueGlobalRootEnumeration()
2494 NTSTATUS ntStatus = STATUS_SUCCESS;
2495 AFSWorkItem *pWorkItem = NULL;
2500 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2501 sizeof(AFSWorkItem),
2503 if (NULL == pWorkItem)
2506 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2507 AFS_TRACE_LEVEL_ERROR,
2508 "AFSQueueGlobalRootEnumeration Failed to allocate work item\n"));
2510 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2513 RtlZeroMemory( pWorkItem,
2514 sizeof(AFSWorkItem));
2516 pWorkItem->Size = sizeof( AFSWorkItem);
2518 pWorkItem->RequestType = AFS_WORK_ENUMERATE_GLOBAL_ROOT;
2520 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2521 AFS_TRACE_LEVEL_VERBOSE,
2522 "AFSQueueGlobalRootEnumeration Workitem %p\n",
2525 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2529 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2530 AFS_TRACE_LEVEL_VERBOSE,
2531 "AFSQueueGlobalRootEnumeration Request complete Status %08lX\n",
2534 if( !NT_SUCCESS( ntStatus))
2537 if( pWorkItem != NULL)
2540 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2543 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2544 AFS_TRACE_LEVEL_ERROR,
2545 "AFSQueueGlobalRootEnumeration Failed to queue request Status %08lX\n",
2549 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2554 "EXCEPTION - AFSQueueGlobalRootEnumeration\n"));
2556 AFSDumpTraceFilesFnc();
2563 AFSQueueStartIos( IN PFILE_OBJECT CacheFileObject,
2564 IN UCHAR FunctionCode,
2565 IN ULONG RequestFlags,
2566 IN AFSIoRun *IoRuns,
2568 IN AFSGatherIo *GatherIo)
2571 NTSTATUS ntStatus = STATUS_SUCCESS;
2572 AFSDeviceExt *pRDRDeviceExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension;
2573 AFSWorkItem *pWorkItem = NULL;
2578 if( BooleanFlagOn( pRDRDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
2581 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2582 AFS_TRACE_LEVEL_ERROR,
2583 "AFSQueueStartIos Failing request, in shutdown\n"));
2585 try_return( ntStatus = STATUS_TOO_LATE);
2589 // Allocate our request structure and send it to the worker
2592 pWorkItem = (AFSWorkItem *)AFSExAllocatePoolWithTag( NonPagedPool,
2593 sizeof( AFSWorkItem),
2596 if( pWorkItem == NULL)
2599 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2600 AFS_TRACE_LEVEL_ERROR,
2601 "AFSQueueStartIos Failed to allocate work item\n"));
2603 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
2606 RtlZeroMemory( pWorkItem,
2607 sizeof( AFSWorkItem));
2609 KeInitializeEvent( &pWorkItem->Event,
2613 pWorkItem->Size = sizeof( AFSWorkItem);
2615 pWorkItem->ProcessID = (ULONGLONG)PsGetCurrentProcessId();
2617 pWorkItem->RequestType = AFS_WORK_START_IOS;
2619 pWorkItem->Specific.CacheAccess.CacheFileObject = CacheFileObject;
2621 pWorkItem->Specific.CacheAccess.FunctionCode = FunctionCode;
2623 pWorkItem->Specific.CacheAccess.RequestFlags = RequestFlags;
2625 pWorkItem->Specific.CacheAccess.IoRuns = IoRuns;
2627 pWorkItem->Specific.CacheAccess.RunCount = RunCount;
2629 pWorkItem->Specific.CacheAccess.GatherIo = GatherIo;
2631 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2632 AFS_TRACE_LEVEL_VERBOSE,
2633 "AFSQueueStartIos Queuing IO Workitem %p\n",
2636 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2640 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2641 AFS_TRACE_LEVEL_VERBOSE,
2642 "AFSQueueStartIos Request complete Status %08lX\n",
2645 if( !NT_SUCCESS( ntStatus))
2648 if( pWorkItem != NULL)
2651 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2655 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2660 "EXCEPTION - AFSQueueStartIos\n"));
2662 AFSDumpTraceFilesFnc();
2669 AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
2670 IN ULONG InvalidateReason)
2673 NTSTATUS ntStatus = STATUS_SUCCESS;
2674 AFSWorkItem *pWorkItem = NULL;
2679 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2680 sizeof(AFSWorkItem),
2682 if (NULL == pWorkItem)
2685 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2686 AFS_TRACE_LEVEL_ERROR,
2687 "AFSQueueInvalidateObject Failed to allocate work item\n"));
2689 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2692 RtlZeroMemory( pWorkItem,
2693 sizeof(AFSWorkItem));
2695 pWorkItem->Size = sizeof( AFSWorkItem);
2697 pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
2699 pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
2701 pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
2703 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2704 AFS_TRACE_LEVEL_VERBOSE,
2705 "AFSQueueInvalidateObject Workitem %p\n",
2708 ntStatus = AFSQueueWorkerRequest( pWorkItem);
2712 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2713 AFS_TRACE_LEVEL_VERBOSE,
2714 "AFSQueueInvalidateObject Request complete Status %08lX\n",
2717 if( !NT_SUCCESS( ntStatus))
2720 if( pWorkItem != NULL)
2722 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2725 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2726 AFS_TRACE_LEVEL_ERROR,
2727 "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
2731 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2736 "EXCEPTION - AFSQueueInvalidateObject\n"));
2738 AFSDumpTraceFilesFnc();
2745 AFSDeferWrite( IN PDEVICE_OBJECT DeviceObject,
2746 IN PFILE_OBJECT FileObject,
2747 IN HANDLE CallingUser,
2749 IN ULONG BytesToWrite,
2750 IN BOOLEAN bRetrying)
2752 NTSTATUS ntStatus = STATUS_SUCCESS;
2753 AFSWorkItem *pWorkItem = NULL;
2759 // Pin the user buffer (first time round only - AFSLockSystemBuffer is
2763 if ( NULL == AFSLockSystemBuffer( Irp, BytesToWrite ))
2766 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2767 AFS_TRACE_LEVEL_ERROR,
2768 "%s Could not pin user memory item\n",
2771 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2774 pWorkItem = (AFSWorkItem *) AFSExAllocatePoolWithTag( NonPagedPool,
2775 sizeof(AFSWorkItem),
2778 if (NULL == pWorkItem)
2781 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING,
2782 AFS_TRACE_LEVEL_ERROR,
2783 "%s Failed to allocate work item\n",
2786 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
2789 RtlZeroMemory( pWorkItem,
2790 sizeof(AFSWorkItem));
2792 pWorkItem->Size = sizeof( AFSWorkItem);
2794 pWorkItem->RequestType = AFS_WORK_DEFERRED_WRITE;
2796 pWorkItem->Specific.AsynchIo.CallingProcess = CallingUser;
2798 pWorkItem->Specific.AsynchIo.Device = DeviceObject;
2800 pWorkItem->Specific.AsynchIo.Irp = Irp;
2802 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2803 AFS_TRACE_LEVEL_VERBOSE,
2808 CcDeferWrite( FileObject, AFSPostedDeferredWrite, pWorkItem, NULL, BytesToWrite, bRetrying);
2810 IoMarkIrpPending(Irp);
2812 ntStatus = STATUS_PENDING;
2814 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
2819 "EXCEPTION - %s \n",
2822 ntStatus = GetExceptionCode();
2827 AFSDbgTrace(( AFS_SUBSYSTEM_WORKER_PROCESSING,
2828 AFS_TRACE_LEVEL_VERBOSE,
2829 "%s complete Status %08lX\n",
2833 if( !NT_SUCCESS( ntStatus))
2836 if( pWorkItem != NULL)
2839 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2842 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2843 AFS_TRACE_LEVEL_ERROR,
2844 "%s Failed to queue request Status %08lX\n",
2854 AFSPostedDeferredWrite( IN PVOID Context1,
2857 UNREFERENCED_PARAMETER( Context2);
2860 AFSWorkItem *pWorkItem = (AFSWorkItem *) Context1;
2862 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2863 AFS_TRACE_LEVEL_ERROR,
2868 ntStatus = AFSQueueIOWorkerRequest( pWorkItem);
2870 if (!NT_SUCCESS( ntStatus))
2873 AFSCompleteRequest( pWorkItem->Specific.AsynchIo.Irp, ntStatus);
2875 ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
2877 AFSDbgTrace(( AFS_SUBSYSTEM_IO_PROCESSING | AFS_SUBSYSTEM_WORKER_PROCESSING,
2878 AFS_TRACE_LEVEL_ERROR,
2879 "%s (%p) Failed to queue request Status %08lX\n",
2881 pWorkItem->Specific.AsynchIo.Irp,