📄 close.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
Close.c
Abstract:
This module implements the File Close routine for Fat called by the
dispatch driver.
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_CLOSE)
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_CLOSE)
ULONG FatMaxDelayedCloseCount;
#define FatAcquireCloseMutex() { \
ASSERT(KeAreApcsDisabled()); \
ExAcquireFastMutexUnsafe( &FatCloseQueueMutex ); \
}
#define FatReleaseCloseMutex() { \
ASSERT(KeAreApcsDisabled()); \
ExReleaseFastMutexUnsafe( &FatCloseQueueMutex ); \
}
//
// Local procedure prototypes
//
VOID
FatQueueClose (
IN PCLOSE_CONTEXT CloseContext,
IN BOOLEAN DelayClose
);
PCLOSE_CONTEXT
FatRemoveClose (
PVCB Vcb OPTIONAL,
PVCB LastVcbHint OPTIONAL
);
VOID
FatCloseWorker (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatFsdClose)
#pragma alloc_text(PAGE, FatFspClose)
#pragma alloc_text(PAGE, FatCommonClose)
#pragma alloc_text(PAGE, FatCloseWorker)
#endif
NTSTATUS
FatFsdClose (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of Close.
Arguments:
VolumeDeviceObject - Supplies the volume device object where the
file exists
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The FSD status for the IRP
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
TYPE_OF_OPEN TypeOfOpen;
BOOLEAN TopLevel;
BOOLEAN VcbDeleted = FALSE;
//
// If we were called with our file system device object instead of a
// volume device object, just complete this request with STATUS_SUCCESS
//
if (FatDeviceIsFatFsdo( VolumeDeviceObject)) {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest( Irp, IO_DISK_INCREMENT );
return STATUS_SUCCESS;
}
DebugTrace(+1, Dbg, "FatFsdClose\n", 0);
//
// Call the common Close routine
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
//
// Get a pointer to the current stack location and the file object
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
FileObject = IrpSp->FileObject;
//
// Decode the file object and set the read-only bit in the Ccb.
//
TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );
if (Ccb && IsFileObjectReadOnly(FileObject)) {
SetFlag( Ccb->Flags, CCB_FLAG_READ_ONLY );
}
try {
PCLOSE_CONTEXT CloseContext = NULL;
//
// If we are top level, WAIT can be TRUE, otherwise make it FALSE
// to avoid deadlocks, unless this is a top
// level request not originating from the system process.
//
BOOLEAN Wait = TopLevel && (PsGetCurrentProcess() != FatData.OurProcess);
//
// Call the common Close routine if we are not delaying this close.
//
if ((((TypeOfOpen == UserFileOpen) ||
(TypeOfOpen == UserDirectoryOpen)) &&
FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE) &&
!FatData.ShutdownStarted) ||
(FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted ) == STATUS_PENDING)) {
//
// Metadata streams have had close contexts preallocated.
//
if (TypeOfOpen == VirtualVolumeFile) {
ASSERT( Vcb->CloseContext != NULL );
CloseContext = Vcb->CloseContext;
Vcb->CloseContext = NULL;
CloseContext->Free = TRUE;
}
else if ((TypeOfOpen == DirectoryFile) || (TypeOfOpen == EaFile)) {
CloseContext = FatAllocateCloseContext( Vcb);
ASSERT( CloseContext != NULL );
CloseContext->Free = TRUE;
} else {
//
// Free up any query template strings before using the close context fields,
// which overlap (union)
//
FatDeallocateCcbStrings( Ccb );
CloseContext = &Ccb->CloseContext;
CloseContext->Free = FALSE;
SetFlag( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT );
}
//
// If the status is pending, then let's get the information we
// need into the close context we already have bagged, complete
// the request, and post it. It is important we allocate nothing
// in the close path.
//
CloseContext->Vcb = Vcb;
CloseContext->Fcb = Fcb;
CloseContext->TypeOfOpen = TypeOfOpen;
//
// Send it off, either to an ExWorkerThread or to the async
// close list.
//
FatQueueClose( CloseContext,
(BOOLEAN)(Fcb && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE)));
} else {
//
// The close proceeded synchronously, so for the metadata objects we
// can now drop the close context we preallocated.
//
if ((TypeOfOpen == VirtualVolumeFile) ||
(TypeOfOpen == DirectoryFile) ||
(TypeOfOpen == EaFile)) {
if (TypeOfOpen == VirtualVolumeFile) {
//
// If the VCB was deleted during the close, the close context for this
// open has already been freed.
//
if (!VcbDeleted) {
CloseContext = Vcb->CloseContext;
Vcb->CloseContext = NULL;
ASSERT( CloseContext != NULL );
} else {
CloseContext = NULL;
}
}
else {
CloseContext = FatAllocateCloseContext( Vcb );
ASSERT( CloseContext != NULL );
}
if (CloseContext != NULL) {
ExFreePool( CloseContext );
}
}
}
FatCompleteRequest( FatNull, Irp, Status );
}
except(FatExceptionFilter( NULL, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with the
// error status that we get back from the execption code.
//
Status = FatProcessException( NULL, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdClose -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
VOID
FatCloseWorker (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
/*++
Routine Description:
This routine is a shim between the IO worker package and FatFspClose.
Arguments:
DeviceObject - Registration device object, unused
Context - Context value, unused
Return Value:
None.
--*/
{
FsRtlEnterFileSystem();
FatFspClose (Context);
FsRtlExitFileSystem();
}
VOID
FatFspClose (
IN PVCB Vcb OPTIONAL
)
/*++
Routine Description:
This routine implements the FSP part of Close.
Arguments:
Vcb - If present, tells us to only close file objects opened on the
specified volume.
Return Value:
None.
--*/
{
PCLOSE_CONTEXT CloseContext;
PVCB CurrentVcb = NULL;
PVCB LastVcb = NULL;
BOOLEAN FreeContext;
ULONG LoopsWithVcbHeld;
DebugTrace(+1, Dbg, "FatFspClose\n", 0);
//
// Set the top level IRP for the true FSP operation.
//
if (!ARGUMENT_PRESENT( Vcb )) {
IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
}
while (CloseContext = FatRemoveClose(Vcb, LastVcb)) {
//
// If we are in the FSP (i.e. Vcb == NULL), then try to keep ahead of
// creates by doing several closes with one acquisition of the Vcb.
//
// Note that we cannot be holding the Vcb on entry to FatCommonClose
// if this is last close as we will try to acquire FatData, and
// worse the volume (and therefore the Vcb) may go away.
//
if (!ARGUMENT_PRESENT(Vcb)) {
if (!FatData.ShutdownStarted) {
if (CloseContext->Vcb != CurrentVcb) {
LoopsWithVcbHeld = 0;
//
// Release a previously held Vcb, if any.
//
if (CurrentVcb != NULL) {
ExReleaseResourceLite( &CurrentVcb->Resource);
}
//
// Get the new Vcb.
//
CurrentVcb = CloseContext->Vcb;
(VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );
} else {
//
// Share the resource occasionally if we seem to be finding a lot
// of closes for a single volume.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -