📄 flush.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
Flush.c
Abstract:
This module implements the File Flush buffers routine for Fat called by the
dispatch driver.
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_FLUSH)
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_FLUSH)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatCommonFlushBuffers)
#pragma alloc_text(PAGE, FatFlushDirectory)
#pragma alloc_text(PAGE, FatFlushFat)
#pragma alloc_text(PAGE, FatFlushFile)
#pragma alloc_text(PAGE, FatFlushVolume)
#pragma alloc_text(PAGE, FatFsdFlushBuffers)
#pragma alloc_text(PAGE, FatFlushDirentForFile)
#pragma alloc_text(PAGE, FatFlushFatEntries)
#pragma alloc_text(PAGE, FatHijackIrpAndFlushDevice)
#endif
//
// Local procedure prototypes
//
NTSTATUS
FatFlushCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
);
NTSTATUS
FatHijackCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Contxt
);
NTSTATUS
FatFsdFlushBuffers (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of Flush buffers.
Arguments:
VolumeDeviceObject - Supplies the volume device object where the
file being flushed exists
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The FSD status for the IRP
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatFsdFlushBuffers\n", 0);
//
// Call the common Cleanup routine, with blocking allowed if synchronous
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonFlushBuffers( IrpContext, Irp );
} except(FatExceptionFilter( IrpContext, 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( IrpContext, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdFlushBuffers -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatCommonFlushBuffers (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for flushing a buffer.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
BOOLEAN VcbAcquired = FALSE;
BOOLEAN FcbAcquired = FALSE;
PDIRENT Dirent;
PBCB DirentBcb = NULL;
PAGED_CODE();
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonFlushBuffers\n", 0);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp);
DebugTrace( 0, Dbg, "->FileObject = %08lx\n", IrpSp->FileObject);
//
// Extract and decode the file object
//
FileObject = IrpSp->FileObject;
TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );
//
// CcFlushCache is always synchronous, so if we can't wait enqueue
// the irp to the Fsp.
//
if ( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ) {
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatCommonFlushBuffers -> %08lx\n", Status );
return Status;
}
Status = STATUS_SUCCESS;
try {
//
// Case on the type of open that we are trying to flush
//
switch (TypeOfOpen) {
case VirtualVolumeFile:
case EaFile:
case DirectoryFile:
DebugTrace(0, Dbg, "Flush that does nothing\n", 0);
break;
case UserFileOpen:
DebugTrace(0, Dbg, "Flush User File Open\n", 0);
(VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );
FcbAcquired = TRUE;
FatVerifyFcb( IrpContext, Fcb );
//
// If the file is cached then flush its cache
//
Status = FatFlushFile( IrpContext, Fcb, Flush );
//
// Also update and flush the file's dirent in the parent directory if the
// file flush worked.
//
if (NT_SUCCESS( Status )) {
//
// Insure that we get the filesize to disk correctly. This is
// benign if it was already good.
//
// (why do we need to do this?)
//
SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED);
FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
//
// Flush the volume file to get any allocation information
// updates to disk.
//
if (FlagOn(Fcb->FcbState, FCB_STATE_FLUSH_FAT)) {
Status = FatFlushFat( IrpContext, Vcb );
ClearFlag(Fcb->FcbState, FCB_STATE_FLUSH_FAT);
}
//
// Set the write through bit so that these modifications
// will be completed with the request.
//
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
}
break;
case UserDirectoryOpen:
//
// If the user had opened the root directory then we'll
// oblige by flushing the volume.
//
if (NodeType(Fcb) != FAT_NTC_ROOT_DCB) {
DebugTrace(0, Dbg, "Flush a directory does nothing\n", 0);
break;
}
case UserVolumeOpen:
DebugTrace(0, Dbg, "Flush User Volume Open, or root dcb\n", 0);
//
// Acquire exclusive access to the Vcb.
//
{
BOOLEAN Finished;
Finished = FatAcquireExclusiveVcb( IrpContext, Vcb );
ASSERT( Finished );
}
VcbAcquired = TRUE;
//
// Mark the volume clean and then flush the volume file,
// and then all directories
//
Status = FatFlushVolume( IrpContext, Vcb, Flush );
//
// If the volume was dirty, do the processing that the delayed
// callback would have done.
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY)) {
//
// Cancel any pending clean volumes.
//
(VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
(VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
//
// The volume is now clean, note it.
//
if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
FatMarkVolume( IrpContext, Vcb, VolumeClean );
ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );
}
//
// Unlock the volume if it is removable.
//
if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE)) {
FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
}
}
break;
default:
FatBugCheck( TypeOfOpen, 0, 0 );
}
FatUnpinBcb( IrpContext, DirentBcb );
FatUnpinRepinnedBcbs( IrpContext );
} finally {
DebugUnwind( FatCommonFlushBuffers );
FatUnpinBcb( IrpContext, DirentBcb );
if (VcbAcquired) { FatReleaseVcb( IrpContext, Vcb ); }
if (FcbAcquired) { FatReleaseFcb( IrpContext, Fcb ); }
//
// If this is a normal termination then pass the request on
// to the target device object.
//
if (!AbnormalTermination()) {
NTSTATUS DriverStatus;
PIO_STACK_LOCATION NextIrpSp;
//
// Get the next stack location, and copy over the stack location
//
NextIrpSp = IoGetNextIrpStackLocation( Irp );
*NextIrpSp = *IrpSp;
//
// Set up the completion routine
//
IoSetCompletionRoutine( Irp,
FatFlushCompletionRoutine,
ULongToPtr( Status ),
TRUE,
TRUE,
TRUE );
//
// Send the request.
//
DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);
Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
Status : DriverStatus;
//
// Free the IrpContext and return to the caller.
//
FatCompleteRequest( IrpContext, FatNull, STATUS_SUCCESS );
}
DebugTrace(-1, Dbg, "FatCommonFlushBuffers -> %08lx\n", Status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -