📄 cachesup.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
cache.c
Abstract:
This module implements the cache management routines for the Fat
FSD and FSP, by calling the Common Cache Manager.
--*/
#include "FatProcs.h"
//
// The Bug check file id for this module
//
#define BugCheckFileId (FAT_BUG_CHECK_CACHESUP)
//
// Local debug trace level
//
#define Dbg (DEBUG_TRACE_CACHESUP)
#if DBG
BOOLEAN
FatIsCurrentOperationSynchedForDcbTeardown (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb
);
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatCloseEaFile)
#pragma alloc_text(PAGE, FatCompleteMdl)
#pragma alloc_text(PAGE, FatOpenDirectoryFile)
#pragma alloc_text(PAGE, FatOpenEaFile)
#pragma alloc_text(PAGE, FatPinMappedData)
#pragma alloc_text(PAGE, FatPrepareWriteDirectoryFile)
#pragma alloc_text(PAGE, FatPrepareWriteVolumeFile)
#pragma alloc_text(PAGE, FatReadDirectoryFile)
#pragma alloc_text(PAGE, FatReadVolumeFile)
#pragma alloc_text(PAGE, FatRepinBcb)
#pragma alloc_text(PAGE, FatSyncUninitializeCacheMap)
#pragma alloc_text(PAGE, FatUnpinRepinnedBcbs)
#pragma alloc_text(PAGE, FatZeroData)
#if DBG
#pragma alloc_text(PAGE, FatIsCurrentOperationSynchedForDcbTeardown)
#endif
#endif
VOID
FatReadVolumeFile (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb,
OUT PVOID *Buffer
)
/*++
Routine Description:
This routine is called when the specified range of sectors is to be
read into the cache. In fat, the volume file only contains the boot
sector, reserved sectors, and the "fat(s)." Thus the volume file is
of fixed size and only extends up to (but not not including) the root
directory entry, and will never move or change size.
The fat volume file is also peculiar in that, since it starts at the
logical beginning of the disk, Vbo == Lbo.
Arguments:
Vcb - Pointer to the VCB for the volume
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
Buffer - Returns a pointer to the sectors, which is valid until unpinned
--*/
{
LARGE_INTEGER Vbo;
PAGED_CODE();
//
// Check to see that all references are within the Bios Parameter Block
// or the fat(s). A special case is made when StartingVbo == 0 at
// mounting time since we do not know how big the fat is.
//
ASSERT( ((StartingVbo == 0) || ((StartingVbo + ByteCount) <= (ULONG)
(FatRootDirectoryLbo( &Vcb->Bpb ) + PAGE_SIZE))));
DebugTrace(+1, Dbg, "FatReadVolumeFile\n", 0);
DebugTrace( 0, Dbg, "Vcb = %08lx\n", Vcb);
DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo);
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
//
// Call the Cache manager to attempt the transfer.
//
Vbo.QuadPart = StartingVbo;
if (!CcMapData( Vcb->VirtualVolumeFile,
&Vbo,
ByteCount,
BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
Bcb,
Buffer )) {
ASSERT( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
//
// Could not read the data without waiting (cache miss).
//
FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
DbgDoit( IrpContext->PinCount += 1 )
DebugTrace(-1, Dbg, "FatReadVolumeFile -> VOID, *BCB = %08lx\n", *Bcb);
return;
}
VOID
FatPrepareWriteVolumeFile (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb,
OUT PVOID *Buffer,
IN BOOLEAN Reversible,
IN BOOLEAN Zero
)
/*++
Routine Description:
This routine first looks to see if the specified range of sectors,
is already in the cache. If so, it increments the BCB PinCount,
sets the BCB dirty, and returns with the location of the sectors.
If the sectors are not in the cache and Wait is TRUE, it finds a
free BCB (potentially causing a flush), and clears out the entire
buffer. Once this is done, it increments the BCB PinCount, sets the
BCB dirty, and returns with the location of the sectors.
If the sectors are not in the cache and Wait is FALSE, this routine
raises STATUS_CANT_WAIT.
Arguments:
Vcb - Pointer to the VCB for the volume
StartingVbo - The virtual offset of the first byte to be written
ByteCount - Number of bytes to be written
Bcb - Returns a pointer to the BCB which is valid until unpinned
Buffer - Returns a pointer to the sectors, which is valid until unpinned
Reversible - Supplies TRUE if the specified range of modification should
be repinned so that the operation can be reversed in a controlled
fashion if errors are encountered.
Zero - Supplies TRUE if the specified range of bytes should be zeroed
--*/
{
LARGE_INTEGER Vbo;
PAGED_CODE();
//
// Check to see that all references are within the Bios Parameter Block
// or the fat(s).
//
ASSERT( ((StartingVbo + ByteCount) <= (ULONG)
(FatRootDirectoryLbo( &Vcb->Bpb ))));
DebugTrace(+1, Dbg, "FatPrepareWriteVolumeFile\n", 0);
DebugTrace( 0, Dbg, "Vcb = %08lx\n", Vcb);
DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", (ULONG)StartingVbo);
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
DebugTrace( 0, Dbg, "Zero = %08lx\n", Zero);
//
// Call the Cache manager to attempt the transfer.
//
Vbo.QuadPart = StartingVbo;
if (!CcPinRead( Vcb->VirtualVolumeFile,
&Vbo,
ByteCount,
BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
Bcb,
Buffer )) {
ASSERT( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
//
// Could not read the data without waiting (cache miss).
//
FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
//
// This keeps the data pinned until we complete the request
// and writes the dirty bit through to the disk.
//
DbgDoit( IrpContext->PinCount += 1 )
try {
if (Zero) {
RtlZeroMemory( *Buffer, ByteCount );
}
FatSetDirtyBcb( IrpContext, *Bcb, Vcb, Reversible );
} finally {
if (AbnormalTermination()) {
FatUnpinBcb(IrpContext, *Bcb);
}
}
DebugTrace(-1, Dbg, "FatPrepareWriteVolumeFile -> VOID, *Bcb = %08lx\n", *Bcb);
return;
}
VOID
FatReadDirectoryFile (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
IN BOOLEAN Pin,
OUT PBCB *Bcb,
OUT PVOID *Buffer,
OUT PNTSTATUS Status
)
/*++
Routine Description:
This routine is called when the specified range of sectors is to be
read into the cache. If the desired range falls beyond the current
cache mapping, the fat will be searched, and if the desired range can
be satisfied, the cache mapping will be extended and the MCB updated
accordingly.
Arguments:
Dcb - Pointer to the DCB for the directory
StartingVbo - The virtual offset of the first desired byte
ByteCount - Number of bytes desired
Pin - Tells us if we should pin instead of just mapping.
Bcb - Returns a pointer to the BCB which is valid until unpinned
Buffer - Returns a pointer to the sectors, which is valid until unpinned
Status - Returns the status of the operation.
--*/
{
LARGE_INTEGER Vbo;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatReadDirectoryFile\n", 0);
DebugTrace( 0, Dbg, "Dcb = %08lx\n", Dcb);
DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo);
DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
//
// Check for the zero case
//
if (ByteCount == 0) {
DebugTrace(0, Dbg, "Nothing to read\n", 0);
*Bcb = NULL;
*Buffer = NULL;
*Status = STATUS_SUCCESS;
DebugTrace(-1, Dbg, "FatReadDirectoryFile -> VOID\n", 0);
return;
}
//
// If we need to create a directory file and initialize the
// cachemap, do so.
//
FatOpenDirectoryFile( IrpContext, Dcb );
//
// Now if the transfer is beyond the allocation size return EOF.
//
if (StartingVbo >= Dcb->Header.AllocationSize.LowPart) {
DebugTrace(0, Dbg, "End of file read for directory\n", 0);
*Bcb = NULL;
*Buffer = NULL;
*Status = STATUS_END_OF_FILE;
DebugTrace(-1, Dbg, "FatReadDirectoryFile -> VOID\n", 0);
return;
}
//
// If the caller is trying to read past the EOF, truncate the
// read.
//
ByteCount = (Dcb->Header.AllocationSize.LowPart - StartingVbo < ByteCount) ?
Dcb->Header.AllocationSize.LowPart - StartingVbo : ByteCount;
ASSERT( ByteCount != 0 );
//
// Call the Cache manager to attempt the transfer.
//
Vbo.QuadPart = StartingVbo;
if (Pin ?
!CcPinRead( Dcb->Specific.Dcb.DirectoryFile,
&Vbo,
ByteCount,
BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
Bcb,
Buffer )
:
!CcMapData( Dcb->Specific.Dcb.DirectoryFile,
&Vbo,
ByteCount,
BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT),
Bcb,
Buffer ) ) {
//
// Could not read the data without waiting (cache miss).
//
*Bcb = NULL;
*Buffer = NULL;
FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
}
DbgDoit( IrpContext->PinCount += 1 )
*Status = STATUS_SUCCESS;
DebugTrace(-1, Dbg, "FatReadDirectoryFile -> VOID, *BCB = %08lx\n", *Bcb);
return;
}
VOID
FatPrepareWriteDirectoryFile (
IN PIRP_CONTEXT IrpContext,
IN PDCB Dcb,
IN VBO StartingVbo,
IN ULONG ByteCount,
OUT PBCB *Bcb,
OUT PVOID *Buffer,
IN BOOLEAN Zero,
IN BOOLEAN Reversible,
OUT PNTSTATUS Status
)
/*++
Routine Description:
This routine first looks to see if the specified range of sectors
is already in the cache. If so, it increments the BCB PinCount,
sets the BCB dirty, and returns TRUE with the location of the sectors.
The IrpContext->Flags .. Wait == TRUE/FALSE actions of this routine are identical to
FatPrepareWriteVolumeFile() above.
Arguments:
Dcb - Pointer to the DCB for the directory
StartingVbo - The virtual offset of the first byte to be written
ByteCount - Number of bytes to be written
Bcb - Returns a pointer to the BCB which is valid until unpinned
Buffer - Returns a pointer to the sectors, which is valid until unpinned
Zero - Supplies TRUE if the specified range of bytes should be zeroed
Reversible - Supplies TRUE if the specified range of modification should
be repinned so that the operation can be reversed in a controlled
fashion if errors are encountered.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -