📄 close.c
字号:
//
// Local support routine
//
BOOLEAN
UdfCommonClosePrivate (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB Fcb,
IN ULONG UserReference,
IN BOOLEAN FromFsd
)
/*++
Routine Description:
This is the worker routine for the close operation. We can be called in
an Fsd thread or from a worker Fsp thread. If called from the Fsd thread
then we acquire the resources without waiting. Otherwise we know it is
safe to wait.
We check to see whether we should post this request to the delayed close
queue. If we are to process the close here then we acquire the Vcb and
Fcb. We will adjust the counts and call our teardown routine to see
if any of the structures should go away.
Arguments:
Vcb - Vcb for this volume.
Fcb - Fcb for this request.
UserReference - Number of user references for this file object. This is
zero for an internal stream.
FromFsd - This request was called from an Fsd thread. Indicates whether
we should wait to acquire resources.
Return Value:
BOOLEAN - TRUE if this thread processed the close, FALSE otherwise.
--*/
{
BOOLEAN CompletedClose;
BOOLEAN RemovedFcb;
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_VCB( Vcb );
ASSERT_FCB( Fcb );
//
// Try to acquire the Vcb and Fcb. If we can't acquire them then return
// and let our caller know he should post the request to the async
// queue.
//
if (UdfAcquireVcbShared( IrpContext, Vcb, FromFsd )) {
if (!UdfAcquireFcbExclusive( IrpContext, Fcb, FromFsd )) {
//
// We couldn't get the Fcb. Release the Vcb and let our caller
// know to post this request.
//
UdfReleaseVcb( IrpContext, Vcb );
return FALSE;
}
//
// We didn't get the Vcb. Let our caller know to post this request.
//
} else {
return FALSE;
}
//
// Lock the Vcb and decrement the reference counts.
//
UdfLockVcb( IrpContext, Vcb );
DebugTrace(( +1, Dbg,
"UdfCommonClosePrivate, Fcb %08x %4s Vcb %d/%d Fcb %d/%d\n", Fcb,
( UserReference? "USER" : "SYS" ),
Vcb->VcbReference,
Vcb->VcbUserReference,
Fcb->FcbReference,
Fcb->FcbUserReference ));
UdfDecrementReferenceCounts( IrpContext, Fcb, 1, UserReference );
DebugTrace(( +0, Dbg,
"UdfCommonClosePrivate, Vcb %d/%d Fcb %d/%d\n",
Vcb->VcbReference,
Vcb->VcbUserReference,
Fcb->FcbReference,
Fcb->FcbUserReference ));
UdfUnlockVcb( IrpContext, Vcb );
//
// Call our teardown routine to see if this object can go away.
// If we don't remove the Fcb then release it.
//
UdfTeardownStructures( IrpContext, Fcb, FALSE, &RemovedFcb );
if (!RemovedFcb) {
UdfReleaseFcb( IrpContext, Fcb );
}
DebugTrace(( -1, Dbg,
"UdfCommonClosePrivate, RemovedFcb %08x -> %c\n",
Fcb,
( RemovedFcb? 'T' : 'F' )));
//
// Release the Vcb and return to our caller. Let him know we completed
// this request.
//
UdfReleaseVcb( IrpContext, Vcb );
return TRUE;
}
VOID
UdfQueueClose (
IN PIRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN ULONG UserReference,
IN BOOLEAN DelayedClose
)
/*++
Routine Description:
This routine is called to queue a request to either the async or delayed
close queue. For the delayed queue we need to allocate a smaller
structure to contain the information about the file object. We do
that so we don't put the larger IrpContext structures into this long
lived queue. If we can allocate this structure then we put this
on the async queue instead.
Arguments:
Fcb - Fcb for this file object.
UserReference - Number of user references for this file object. This is
zero for an internal stream.
DelayedClose - Indicates whether this should go on the async or delayed
close queue.
Return Value:
None
--*/
{
PIRP_CONTEXT_LITE IrpContextLite = NULL;
BOOLEAN StartWorker = FALSE;
PAGED_CODE();
//
// Check inputs.
//
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_FCB( Fcb );
//
// Start with the delayed queue request. We can move this to the async
// queue if there is an allocation failure.
//
if (DelayedClose) {
//
// Try to allocate non-paged pool for the IRP_CONTEXT_LITE.
//
IrpContextLite = UdfCreateIrpContextLite( IrpContext );
}
//
// We want to clear the top level context in this thread if
// necessary. Call our cleanup routine to do the work.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
UdfCleanupIrpContext( IrpContext, TRUE );
//
// Synchronize with the UdfData lock.
//
UdfLockUdfData();
DebugTrace(( +1, Dbg,
"UdfQueueClose, Fcb %08x %4s %5s\n",
Fcb,
( UserReference? "USER" : "SYS" ),
( IrpContextLite? "DELAY" : "ASYNC" )));
//
// If we have an IrpContext then put the request on the delayed close queue.
//
if (IrpContextLite != NULL) {
//
// Initialize the IrpContextLite.
//
IrpContextLite->NodeTypeCode = UDFS_NTC_IRP_CONTEXT_LITE;
IrpContextLite->NodeByteSize = sizeof( IRP_CONTEXT_LITE );
IrpContextLite->Fcb = Fcb;
IrpContextLite->UserReference = UserReference;
IrpContextLite->RealDevice = IrpContext->RealDevice;
//
// Add this to the delayed close list and increment
// the count.
//
InsertTailList( &UdfData.DelayedCloseQueue,
&IrpContextLite->DelayedCloseLinks );
UdfData.DelayedCloseCount += 1;
//
// If we are above our threshold then start the delayed
// close operation.
//
if (UdfData.DelayedCloseCount > UdfData.MaxDelayedCloseCount) {
UdfData.ReduceDelayedClose = TRUE;
if (!UdfData.FspCloseActive) {
UdfData.FspCloseActive = TRUE;
StartWorker = TRUE;
}
}
//
// Unlock the global data.
//
UdfUnlockUdfData();
//
// Cleanup the IrpContext.
//
UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
//
// Otherwise drop into the async case below.
//
} else {
//
// Store the information about the file object into the IrpContext.
//
IrpContext->Irp = (PIRP) Fcb;
IrpContext->ExceptionStatus = (NTSTATUS) UserReference;
//
// Add this to the async close list and increment the count.
//
InsertTailList( &UdfData.AsyncCloseQueue,
&IrpContext->WorkQueueItem.List );
UdfData.AsyncCloseCount += 1;
//
// Remember to start the Fsp close thread if not currently started.
//
if (!UdfData.FspCloseActive) {
UdfData.FspCloseActive = TRUE;
StartWorker = TRUE;
}
//
// Unlock the global data.
//
UdfUnlockUdfData();
}
//
// Start the FspClose thread if we need to.
//
if (StartWorker) {
ExQueueWorkItem( &UdfData.CloseItem, CriticalWorkQueue );
}
DebugTrace(( -1, Dbg, "UdfQueueClose -> VOID\n" ));
//
// Return to our caller.
//
return;
}
//
// Local support routine
//
PIRP_CONTEXT
UdfRemoveClose (
IN PVCB Vcb OPTIONAL
)
/*++
Routine Description:
Arguments:
This routine is called to scan the async and delayed close queues looking
for a suitable entry. If the Vcb is specified then we scan both queues
looking for an entry with the same Vcb. Otherwise we will look in the
async queue first for any close item. If none found there then we look
in the delayed close queue provided that we have triggered the delayed
close operation.
Return Value:
PIRP_CONTEXT - NULL if no work item found. Otherwise it is the pointer to
either the IrpContext or IrpContextLite for this request.
--*/
{
PIRP_CONTEXT IrpContext = NULL;
PIRP_CONTEXT NextIrpContext;
PIRP_CONTEXT_LITE NextIrpContextLite;
PLIST_ENTRY Entry;
PAGED_CODE();
ASSERT_OPTIONAL_VCB( Vcb );
//
// Lock the UdfData to perform the scan.
//
UdfLockUdfData();
//
// First check the list of async closes.
//
Entry = UdfData.AsyncCloseQueue.Flink;
while (Entry != &UdfData.AsyncCloseQueue) {
//
// Extract the IrpContext.
//
NextIrpContext = CONTAINING_RECORD( Entry,
IRP_CONTEXT,
WorkQueueItem.List );
//
// If no Vcb was specified or this Vcb is for our volume
// then perform the close.
//
if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContext->Vcb == Vcb)) {
RemoveEntryList( Entry );
UdfData.AsyncCloseCount -= 1;
IrpContext = NextIrpContext;
break;
}
//
// Move to the next entry.
//
Entry = Entry->Flink;
}
//
// If we didn't find anything look through the delayed close
// queue.
//
// We will only check the delayed close queue if we were given
// a Vcb or the delayed close operation is active.
//
if ((IrpContext == NULL) &&
(ARGUMENT_PRESENT( Vcb ) ||
(UdfData.ReduceDelayedClose &&
(UdfData.DelayedCloseCount > UdfData.MinDelayedCloseCount)))) {
Entry = UdfData.DelayedCloseQueue.Flink;
while (Entry != &UdfData.DelayedCloseQueue) {
//
// Extract the IrpContext.
//
NextIrpContextLite = CONTAINING_RECORD( Entry,
IRP_CONTEXT_LITE,
DelayedCloseLinks );
//
// If no Vcb was specified or this Vcb is for our volume
// then perform the close.
//
if (!ARGUMENT_PRESENT( Vcb ) || (NextIrpContextLite->Fcb->Vcb == Vcb)) {
RemoveEntryList( Entry );
UdfData.DelayedCloseCount -= 1;
IrpContext = (PIRP_CONTEXT) NextIrpContextLite;
break;
}
//
// Move to the next entry.
//
Entry = Entry->Flink;
}
}
//
// If the Vcb wasn't specified and we couldn't find an entry
// then turn off the Fsp thread.
//
if (!ARGUMENT_PRESENT( Vcb ) && (IrpContext == NULL)) {
UdfData.FspCloseActive = FALSE;
UdfData.ReduceDelayedClose = FALSE;
}
//
// Unlock the global data.
//
UdfUnlockUdfData();
return IrpContext;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -