pDevExt->Specific.Library.WorkerCount = 0;
KeInitializeEvent( &pDevExt->Specific.Library.WorkerQueueHasItems,
- NotificationEvent,
+ SynchronizationEvent,
FALSE);
//
pDevExt->Specific.Library.IOWorkerCount = 0;
KeInitializeEvent( &pDevExt->Specific.Library.IOWorkerQueueHasItems,
- NotificationEvent,
+ SynchronizationEvent,
FALSE);
//
pDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
//
- // Loop through the workers shutting them down
+ // Loop through the workers shutting them down in two stages.
+ // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
+ // stop processing requests. Second, call AFSShutdownWorkerThread()
+ // to wake the workers and wait for them to exit.
//
pCurrentWorker = pDevExt->Specific.Library.PoolHead;
while( index < pDevExt->Specific.Library.WorkerCount)
{
+ ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
+
+ pCurrentWorker = pCurrentWorker->fLink;
+
+ if ( pCurrentWorker == NULL)
+ {
+
+ break;
+ }
+
+ index++;
+ }
+
+ pCurrentWorker = pDevExt->Specific.Library.PoolHead;
+
+ index = 0;
+
+ while( index < pDevExt->Specific.Library.WorkerCount)
+ {
+
ntStatus = AFSShutdownWorkerThread( pCurrentWorker);
pNextWorker = pCurrentWorker->fLink;
ExDeleteResourceLite( &pDevExt->Specific.Library.QueueLock);
//
- // Loop through the IO workers shutting them down
+ // Loop through the IO workers shutting them down in two stages.
+ // First, clear AFS_WORKER_PROCESS_REQUESTS so that workers
+ // stop processing requests. Second, call AFSShutdownWorkerThread()
+ // to wake the workers and wait for them to exit.
//
pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
while( index < pDevExt->Specific.Library.IOWorkerCount)
{
+ ClearFlag( pCurrentWorker->State, AFS_WORKER_PROCESS_REQUESTS);
+
+ pCurrentWorker = pCurrentWorker->fLink;
+
+ if ( pCurrentWorker == NULL)
+ {
+
+ break;
+ }
+
+ index++;
+ }
+
+ pCurrentWorker = pDevExt->Specific.Library.IOPoolHead;
+
+ index = 0;
+
+ while( index < pDevExt->Specific.Library.IOWorkerCount)
+ {
+
ntStatus = AFSShutdownIOWorkerThread( pCurrentWorker);
pNextWorker = pCurrentWorker->fLink;
//
// Description:
//
-// This function shusdown a worker thread in the pool
+// This function shutsdown a worker thread in the pool
//
// Return:
//
{
//
- // Clear the 'keep processing' flag
- //
-
- ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
-
- //
// Wake up the thread if it is a sleep
//
{
//
- // Clear the 'keep processing' flag
- //
-
- ClearFlag( PoolContext->State, AFS_WORKER_PROCESS_REQUESTS);
-
- //
// Wake up the thread if it is a sleep
//
AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
AFSWorkItem *pWorkItem;
BOOLEAN freeWorkItem = TRUE;
- BOOLEAN exitThread = FALSE;
AFSDeviceExt *pLibraryDevExt = NULL;
LONG lCount;
0,
FALSE);
-
//
// Indicate we are initialized
//
SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+ ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
{
- ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
- Executive,
- KernelMode,
- FALSE,
- NULL);
-
if( !NT_SUCCESS( ntStatus))
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_ERROR,
"AFSWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
+
+ ntStatus = STATUS_SUCCESS;
}
else
{
pWorkItem = AFSRemoveWorkItem();
- if( pWorkItem != NULL)
+ if( pWorkItem == NULL)
+ {
+
+ ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ }
+ else
{
freeWorkItem = TRUE;
break;
}
+ case AFS_WORK_INVALIDATE_OBJECT:
+ {
+
+ AFSPerformObjectInvalidate( pWorkItem->Specific.Invalidate.ObjectInfo,
+ pWorkItem->Specific.Invalidate.InvalidateReason);
+
+ freeWorkItem = TRUE;
+
+ break;
+ }
+
case AFS_WORK_START_IOS:
{
ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
}
+
+ ntStatus = STATUS_SUCCESS;
}
}
} // worker thread loop
+ ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+
+ // Wake up another worker so they too can exit
+
+ KeSetEvent( &pLibraryDevExt->Specific.Library.WorkerQueueHasItems,
+ 0,
+ FALSE);
+
PsTerminateSystemThread( 0);
return;
AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)Context;
AFSWorkItem *pWorkItem;
BOOLEAN freeWorkItem = TRUE;
- BOOLEAN exitThread = FALSE;
AFSDeviceExt *pLibraryDevExt = NULL, *pRdrDevExt = NULL;
pLibraryDevExt = (AFSDeviceExt *)AFSLibraryDeviceObject->DeviceExtension;
SetFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+ ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
while( BooleanFlagOn( pPoolContext->State, AFS_WORKER_PROCESS_REQUESTS))
{
- ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
- Executive,
- KernelMode,
- FALSE,
- NULL);
-
if( !NT_SUCCESS( ntStatus))
{
AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
AFS_TRACE_LEVEL_ERROR,
"AFSIOWorkerThread Wait for queue items failed Status %08lX\n", ntStatus);
+
+ ntStatus = STATUS_SUCCESS;
}
else
{
pWorkItem = AFSRemoveIOWorkItem();
- if( pWorkItem != NULL)
+ if( pWorkItem == NULL)
+ {
+
+ ntStatus = KeWaitForSingleObject( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ }
+ else
{
freeWorkItem = TRUE;
ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
}
+
+ ntStatus = STATUS_SUCCESS;
}
}
} // worker thread loop
+ ClearFlag( pPoolContext->State, AFS_WORKER_INITIALIZED);
+
+ // Wake up another IOWorker so they too can exit
+
+ KeSetEvent( &pLibraryDevExt->Specific.Library.IOWorkerQueueHasItems,
+ 0,
+ FALSE);
+
PsTerminateSystemThread( 0);
return;
AFSWorkQueueContext *pPoolContext = (AFSWorkQueueContext *)&AFSGlobalRoot->VolumeWorkerContext;
AFSDeviceExt *pControlDeviceExt = NULL;
AFSDeviceExt *pRDRDeviceExt = NULL;
- BOOLEAN exitThread = FALSE;
LARGE_INTEGER DueTime;
LONG TimeOut;
KTIMER Timer;
AFSDirectoryCB *pCurrentDirEntry = NULL, *pNextDirEntry = NULL;
BOOLEAN bReleaseVolumeLock = FALSE;
AFSVolumeCB *pVolumeCB = NULL, *pNextVolume = NULL;
+ AFSFcb *pFcb = NULL;
+ LONG lFileType;
LARGE_INTEGER liCurrentTime;
BOOLEAN bVolumeObject = FALSE;
LONG lCount;
continue;
}
- if( pVolumeCB->ObjectInfoListHead == NULL &&
- pVolumeCB != AFSGlobalRoot)
+ if( pVolumeCB->ObjectInfoListHead == NULL)
{
AFSReleaseResource( pVolumeCB->VolumeLock);
if( pCurrentObject->Fcb != NULL)
{
- //
- // Acquire and drop the Fcb resource to synchronize
- // with a potentially active AFSCleanup() which sets
- // the OpenReferenceCount to zero while holding the
- // resource.
- //
-
- AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
- TRUE);
-
- AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
-
- AFSRemoveFcb( pCurrentObject->Fcb);
+ AFSRemoveFcb( &pCurrentObject->Fcb);
}
if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB != NULL)
if( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
{
- AFSRemoveFcb( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+ AFSRemoveFcb( &pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
}
AFSDeleteObjectInfo( pCurrentObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSPrimaryWorker Deleting deleted object %08lX\n",
+ "AFSPrimaryVolumeWorkerThread Deleting deleted object %08lX\n",
pCurrentObject);
AFSDeleteObjectInfo( pCurrentObject);
pCurrentChildObject = pCurrentDirEntry->ObjectInformation;
+ pFcb = NULL;
+
AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSPrimaryWorker Deleting DE %wZ Object %08lX\n",
+ "AFSPrimaryVolumeWorkerThread Deleting DE %wZ Object %08lX\n",
&pCurrentDirEntry->NameInformation.FileName,
pCurrentChildObject);
if( pCurrentChildObject->Fcb != NULL)
{
- if( pCurrentChildObject->FileType == AFS_FILE_TYPE_FILE)
- {
-
- AFSCleanupFcb( pCurrentChildObject->Fcb,
- TRUE);
- }
+ pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)&pCurrentChildObject->Fcb, NULL, (PVOID)pCurrentChildObject->Fcb);
- //
- // Acquire and drop the Fcb resource to synchronize
- // with a potentially active AFSCleanup() which sets
- // the OpenReferenceCount to zero while holding the
- // resource.
- //
-
- AFSAcquireExcl( &pCurrentChildObject->Fcb->NPFcb->Resource,
- TRUE);
-
- AFSReleaseResource( &pCurrentChildObject->Fcb->NPFcb->Resource);
-
- AFSRemoveFcb( pCurrentChildObject->Fcb);
+ lFileType = pCurrentChildObject->FileType;
}
if( pCurrentChildObject->FileType == AFS_FILE_TYPE_DIRECTORY &&
if( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb != NULL)
{
- AFSRemoveFcb( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
+ AFSRemoveFcb( &pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation->Fcb);
}
AFSDeleteObjectInfo( pCurrentChildObject->Specific.Directory.PIOCtlDirectoryCB->ObjectInformation);
AFSDbgLogMsg( AFS_SUBSYSTEM_CLEANUP_PROCESSING,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSPrimaryWorker Deleting object %08lX\n",
+ "AFSPrimaryVolumeWorkerThread Deleting object %08lX\n",
pCurrentChildObject);
AFSDeleteObjectInfo( pCurrentChildObject);
}
pCurrentDirEntry = pNextDirEntry;
+
+ if ( pFcb != NULL)
+ {
+
+ if( lFileType == AFS_FILE_TYPE_FILE)
+ {
+ //
+ // We must not hold pVolumeCB->ObjectInfoTree.TreeLock exclusive
+ // across an AFSCleanupFcb call since it can deadlock with an
+ // invalidation call from the service.
+ //
+
+ AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
+
+ AFSCleanupFcb( pFcb,
+ TRUE);
+
+ AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
+ TRUE);
+ }
+
+ AFSRemoveFcb( &pFcb);
+ }
}
pCurrentObject->Specific.Directory.DirectoryNodeListHead = NULL;
AFSDbgLogMsg( AFS_SUBSYSTEM_DIR_NODE_COUNT,
AFS_TRACE_LEVEL_VERBOSE,
- "AFSPrimaryWorker Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
+ "AFSPrimaryVolumeWorkerThread Reset count to 0 on parent FID %08lX-%08lX-%08lX-%08lX\n",
pCurrentObject->FileId.Cell,
pCurrentObject->FileId.Volume,
pCurrentObject->FileId.Vnode,
pCurrentObject->Fcb->OpenReferenceCount == 0))
{
- AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
-
- if( AFSAcquireExcl( pVolumeCB->ObjectInfoTree.TreeLock,
- FALSE))
- {
-
- if( pCurrentObject->Fcb != NULL)
- {
-
- AFSCleanupFcb( pCurrentObject->Fcb,
- TRUE);
-
- //
- // Acquire and drop the Fcb resource to synchronize
- // with a potentially active AFSCleanup() which sets
- // the OpenReferenceCount to zero while holding the
- // resource.
- //
-
- AFSAcquireExcl( &pCurrentObject->Fcb->NPFcb->Resource,
- TRUE);
-
- AFSReleaseResource( &pCurrentObject->Fcb->NPFcb->Resource);
-
- AFSRemoveFcb( pCurrentObject->Fcb);
- }
-
- AFSDeleteObjectInfo( pCurrentObject);
-
- AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
-
- pCurrentObject = pNextObject;
+ pFcb = (AFSFcb *) InterlockedCompareExchangePointer( (PVOID *)&pCurrentObject->Fcb, NULL, (PVOID)pCurrentObject->Fcb);
- continue;
- }
- else
+ if( pFcb != NULL)
{
- bReleaseVolumeLock = FALSE;
+ AFSCleanupFcb( pFcb,
+ TRUE);
- break;
+ AFSRemoveFcb( &pFcb);
}
- }
- else if( pCurrentObject->Fcb != NULL)
- {
AFSReleaseResource( pVolumeCB->ObjectInfoTree.TreeLock);
FALSE))
{
- AFSCleanupFcb( pCurrentObject->Fcb,
- FALSE);
+ AFSDeleteObjectInfo( pCurrentObject);
AFSConvertToShared( pVolumeCB->ObjectInfoTree.TreeLock);
break;
}
}
+ else if( pCurrentObject->Fcb != NULL)
+ {
+
+ AFSCleanupFcb( pCurrentObject->Fcb,
+ FALSE);
+ }
}
pCurrentObject = pNextObject;
{
pDevExt->Specific.Library.QueueTail = NULL;
+ }
+ else
+ {
- KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
+ //
+ // Wake up another worker
+ //
+
+ KeSetEvent( &(pDevExt->Specific.Library.WorkerQueueHasItems),
+ 0,
+ FALSE);
}
}
- else
- {
- KeResetEvent(&(pDevExt->Specific.Library.WorkerQueueHasItems));
- }
AFSReleaseResource( &pDevExt->Specific.Library.QueueLock);
{
pDevExt->Specific.Library.IOQueueTail = NULL;
+ }
+ else
+ {
- KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
+ //
+ // Wake up another worker
+ //
+
+ KeSetEvent( &(pDevExt->Specific.Library.IOWorkerQueueHasItems),
+ 0,
+ FALSE);
}
}
- else
- {
- KeResetEvent(&(pDevExt->Specific.Library.IOWorkerQueueHasItems));
- }
AFSReleaseResource( &pDevExt->Specific.Library.IOQueueLock);
return ntStatus;
}
+
+NTSTATUS
+AFSQueueInvalidateObject( IN AFSObjectInfoCB *ObjectInfo,
+ IN ULONG InvalidateReason)
+{
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ AFSWorkItem *pWorkItem = NULL;
+
+ __try
+ {
+
+ pWorkItem = (AFSWorkItem *) AFSLibExAllocatePoolWithTag( NonPagedPool,
+ sizeof(AFSWorkItem),
+ AFS_WORK_ITEM_TAG);
+ if (NULL == pWorkItem)
+ {
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_IO_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSQueueInvalidateObject Failed to allocate work item\n");
+
+ try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES );
+ }
+
+ RtlZeroMemory( pWorkItem,
+ sizeof(AFSWorkItem));
+
+ pWorkItem->Size = sizeof( AFSWorkItem);
+
+ pWorkItem->RequestType = AFS_WORK_INVALIDATE_OBJECT;
+
+ pWorkItem->Specific.Invalidate.ObjectInfo = ObjectInfo;
+
+ pWorkItem->Specific.Invalidate.InvalidateReason = InvalidateReason;
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSQueueInvalidateObject Workitem %08lX\n",
+ pWorkItem);
+
+ ntStatus = AFSQueueWorkerRequest( pWorkItem);
+
+try_exit:
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_WORKER_PROCESSING,
+ AFS_TRACE_LEVEL_VERBOSE,
+ "AFSQueueInvalidateObject Request complete Status %08lX\n",
+ ntStatus);
+
+ if( !NT_SUCCESS( ntStatus))
+ {
+
+ if( pWorkItem != NULL)
+ {
+ ExFreePoolWithTag( pWorkItem, AFS_WORK_ITEM_TAG);
+ }
+
+ AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+ AFS_TRACE_LEVEL_ERROR,
+ "AFSQueueInvalidateObject Failed to queue request Status %08lX\n",
+ ntStatus);
+ }
+ }
+ __except( AFSExceptionFilter( GetExceptionCode(), GetExceptionInformation()) )
+ {
+
+ AFSDbgLogMsg( 0,
+ 0,
+ "EXCEPTION - AFSQueueInvalidateObject\n");
+ }
+
+ return ntStatus;
+}