📄 cachesup.c
字号:
This routine frees all of the repinned bcbs, stored in an IRP context.
Arguments:
Return Value:
None.
--*/
{
IO_STATUS_BLOCK RaiseIosb;
PREPINNED_BCBS Repinned;
BOOLEAN WriteThroughToDisk;
PFILE_OBJECT FileObject = NULL;
BOOLEAN ForceVerify = FALSE;
ULONG i;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatUnpinRepinnedBcbs\n", 0 );
DebugTrace( 0, Dbg, "IrpContext = %08lx\n", IrpContext );
//
// The algorithm for this procedure is to scan the entire list of
// repinned records unpinning any repinned bcbs. We start off
// with the first record in the irp context, and while there is a
// record to scan we do the following loop.
//
Repinned = &IrpContext->Repinned;
RaiseIosb.Status = STATUS_SUCCESS;
//
// If the request is write through or the media is deferred flush,
// unpin the bcb's write through.
//
WriteThroughToDisk = (BOOLEAN) (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH) &&
IrpContext->Vcb != NULL &&
(FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH) ||
FlagOn(IrpContext->Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH)));
while (Repinned != NULL) {
//
// For every non-null entry in the repinned record unpin the
// repinned entry.
//
// If the this is removable media (therefore all requests write-
// through) and the write fails, purge the cache so that we throw
// away the modifications as we will be returning an error to the
// user.
//
for (i = 0; i < REPINNED_BCBS_ARRAY_SIZE; i += 1) {
if (Repinned->Bcb[i] != NULL) {
IO_STATUS_BLOCK Iosb;
if (WriteThroughToDisk &&
FlagOn(IrpContext->Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH)) {
FileObject = CcGetFileObjectFromBcb( Repinned->Bcb[i] );
}
CcUnpinRepinnedBcb( Repinned->Bcb[i],
WriteThroughToDisk,
&Iosb );
if ( !NT_SUCCESS(Iosb.Status) ) {
if (RaiseIosb.Status == STATUS_SUCCESS) {
RaiseIosb = Iosb;
}
//
// If this was a writethrough device, purge the cache,
// except for Irp major codes that either don't handle
// the error paths correctly or are simple victims like
// cleanup.c.
//
if (FileObject &&
(IrpContext->MajorFunction != IRP_MJ_CLEANUP) &&
(IrpContext->MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
(IrpContext->MajorFunction != IRP_MJ_SET_INFORMATION)) {
//
// The call to CcPurgeCacheSection() below will
// purge the entire file from memory. It will also
// block until all the file's BCB's are pinned.
//
// We end up in a deadlock situation of there
// are any other pinned BCB's in this IRP context
// so the first thing we do is search the list
// for BCB's pinned in the same file and unpin
// them.
//
// We are probably not going to lose data because
// it's safe to assume that all flushes will
// fail after the first one fails.
//
ULONG j;
for (j = i + 1; j < REPINNED_BCBS_ARRAY_SIZE; j++) {
if (Repinned->Bcb[j] != NULL) {
if (CcGetFileObjectFromBcb( Repinned->Bcb[j] ) == FileObject) {
CcUnpinRepinnedBcb( Repinned->Bcb[j],
FALSE,
&Iosb );
Repinned->Bcb[j] = NULL;
}
}
}
CcPurgeCacheSection( FileObject->SectionObjectPointer,
NULL,
0,
FALSE );
//
// Force a verify operation here since who knows
// what state things are in.
//
ForceVerify = TRUE;
}
}
Repinned->Bcb[i] = NULL;
}
}
//
// Now find the next repinned record in the list, and possibly
// delete the one we've just processed.
//
if (Repinned != &IrpContext->Repinned) {
PREPINNED_BCBS Saved;
Saved = Repinned->Next;
ExFreePool( Repinned );
Repinned = Saved;
} else {
Repinned = Repinned->Next;
IrpContext->Repinned.Next = NULL;
}
}
//
// Now if we weren't completely successful in the our unpin
// then raise the iosb we got
//
if (!NT_SUCCESS(RaiseIosb.Status)) {
if (ForceVerify && FileObject) {
SetFlag(FileObject->DeviceObject->Flags, DO_VERIFY_VOLUME);
IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
FileObject->DeviceObject );
}
if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_RAISE )) {
IrpContext->OriginatingIrp->IoStatus = RaiseIosb;
FatNormalizeAndRaiseStatus( IrpContext, RaiseIosb.Status );
}
}
DebugTrace(-1, Dbg, "FatUnpinRepinnedBcbs -> VOID\n", 0 );
return;
}
FINISHED
FatZeroData (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_OBJECT FileObject,
IN ULONG StartingZero,
IN ULONG ByteCount
)
/*++
**** Temporary function - Remove when CcZeroData is capable of handling
non sector aligned requests.
--*/
{
LARGE_INTEGER ZeroStart = {0,0};
LARGE_INTEGER BeyondZeroEnd = {0,0};
ULONG SectorSize;
BOOLEAN Finished;
PAGED_CODE();
SectorSize = (ULONG)Vcb->Bpb.BytesPerSector;
ZeroStart.LowPart = (StartingZero + (SectorSize - 1)) & ~(SectorSize - 1);
//
// Detect overflow if we were asked to zero in the last sector of the file,
// which must be "zeroed" already (or we're in trouble).
//
if (StartingZero != 0 && ZeroStart.LowPart == 0) {
return TRUE;
}
//
// Note that BeyondZeroEnd can take the value 4gb.
//
BeyondZeroEnd.QuadPart = ((ULONGLONG) StartingZero + ByteCount + (SectorSize - 1))
& (~((LONGLONG) SectorSize - 1));
//
// If we were called to just zero part of a sector we are in trouble.
//
if ( ZeroStart.QuadPart == BeyondZeroEnd.QuadPart ) {
return TRUE;
}
Finished = CcZeroData( FileObject,
&ZeroStart,
&BeyondZeroEnd,
BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
return Finished;
}
NTSTATUS
FatCompleteMdl (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This routine performs the function of completing Mdl read and write
requests. It should be called only from FatFsdRead and FatFsdWrite.
Arguments:
Irp - Supplies the originating Irp.
Return Value:
NTSTATUS - Will always be STATUS_PENDING or STATUS_SUCCESS.
--*/
{
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION IrpSp;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatCompleteMdl\n", 0 );
DebugTrace( 0, Dbg, "IrpContext = %08lx\n", IrpContext );
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
//
// Do completion processing.
//
FileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
switch( IrpContext->MajorFunction ) {
case IRP_MJ_READ:
CcMdlReadComplete( FileObject, Irp->MdlAddress );
break;
case IRP_MJ_WRITE:
IrpSp = IoGetCurrentIrpStackLocation( Irp );
ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ));
CcMdlWriteComplete( FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress );
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
default:
DebugTrace( DEBUG_TRACE_ERROR, 0, "Illegal Mdl Complete.\n", 0);
FatBugCheck( IrpContext->MajorFunction, 0, 0 );
}
//
// Mdl is now deallocated.
//
Irp->MdlAddress = NULL;
//
// Complete the request and exit right away.
//
FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
DebugTrace(-1, Dbg, "FatCompleteMdl -> STATUS_SUCCESS\n", 0 );
return STATUS_SUCCESS;
}
VOID
FatSyncUninitializeCacheMap (
IN PIRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject
)
/*++
Routine Description:
The routine performs a CcUnitializeCacheMap to LargeZero synchronously. That
is it waits on the Cc event. This call is useful when we want to be certain
when a close will actually some in.
Return Value:
None.
--*/
{
CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent;
NTSTATUS WaitStatus;
PAGED_CODE();
KeInitializeEvent( &UninitializeCompleteEvent.Event,
SynchronizationEvent,
FALSE);
CcUninitializeCacheMap( FileObject,
&FatLargeZero,
&UninitializeCompleteEvent );
//
// Now wait for the cache manager to finish purging the file.
// This will garentee that Mm gets the purge before we
// delete the Vcb.
//
WaitStatus = KeWaitForSingleObject( &UninitializeCompleteEvent.Event,
Executive,
KernelMode,
FALSE,
NULL);
ASSERT(WaitStatus == STATUS_SUCCESS);
}
VOID
FatPinMappedData (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb
)
/*++
Routine Description:
This routine pins data that was previously mapped before setting it dirty.
Arguments:
Dcb - Pointer to the DCB for the directory
StartingVbo - The virtual offset of the first desired byte
ByteCount - Number of bytes desired
Bcb - Returns a pointer to the BCB which is valid until unpinned
--*/
{
LARGE_INTEGER Vbo;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatPinMappedData\n", 0);
DebugTrace( 0, Dbg, "Dcb = %08lx\n", Dcb);
DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo);
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
//
// Call the Cache manager to perform the operation.
//
Vbo.QuadPart = StartingVbo;
if (!CcPinMappedData( Dcb->Specific.Dcb.DirectoryFile,
&Vbo,
ByteCount,
BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
Bcb )) {
//
// Could not pin the data without waiting (cache miss).
//
FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
DebugTrace(-1, Dbg, "FatReadDirectoryFile -> VOID, *BCB = %08lx\n", *Bcb);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -