📄 allocsup.c
字号:
FatEntry = (FAT_ENTRY)FatGetIndexFromLbo( Vcb, CurrentLbo );
//
// ASSERT that CurrentVbo and CurrentLbo are now cluster alligned.
// The assumption here, is that only whole clusters of Vbos and Lbos
// are mapped in the Mcb.
//
ASSERT( ((CurrentLbo - Vcb->AllocationSupport.FileAreaLbo)
% BytesPerCluster == 0) &&
(CurrentVbo % BytesPerCluster == 0) );
//
// Starting from the first Vbo after the last Mcb entry, scan through
// the Fat looking for our Vbo. We continue through the Fat until we
// hit a noncontiguity beyond the desired Vbo, or the last cluster.
//
while ( !LastCluster ) {
//
// Get the next fat entry, and update our Current variables.
//
FatLookupFatEntry( IrpContext, Vcb, FatEntry, &FatEntry, &Context );
PriorLbo = CurrentLbo;
CurrentLbo = FatGetLboFromIndex( Vcb, FatEntry );
CurrentVbo += BytesPerCluster;
switch ( FatInterpretClusterType( Vcb, FatEntry )) {
//
// Check for a break in the Fat allocation chain.
//
case FatClusterAvailable:
case FatClusterReserved:
case FatClusterBad:
DebugTrace( 0, Dbg, "Break in allocation chain, entry = %d\n", FatEntry);
DebugTrace(-1, Dbg, "FatLookupFileAllocation -> Fat Corrupt. Raise Status.\n", 0);
FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
break;
//
// If this is the last cluster, we must update the Mcb and
// exit the loop.
//
case FatClusterLast:
//
// Assert we know where the current run started. If the
// Mcb was empty when we were called, thenFirstLboOfCurrentRun
// was set to the start of the file. If the Mcb contained an
// entry, then FirstLboOfCurrentRun was set on the first
// iteration through the loop. Thus if FirstLboOfCurrentRun
// is 0, then there was an Mcb entry and we are on our first
// iteration, meaing that the last cluster in the Mcb was
// really the last allocated cluster, but we checked Vbo
// against AllocationSize, and found it OK, thus AllocationSize
// must be too large.
//
// Note that, when we finally arrive here, CurrentVbo is actually
// the first Vbo beyond the file allocation and CurrentLbo is
// meaningless.
//
DebugTrace( 0, Dbg, "Read last cluster of file.\n", 0);
//
// Detect the case of the maximal file. Note that this really isn't
// a proper Vbo - those are zero-based, and this is a one-based number.
// The maximal file, of 2^32 - 1 bytes, has a maximum byte offset of
// 2^32 - 2.
//
// Just so we don't get confused here.
//
if (CurrentVbo == 0) {
*EndOnMax = TRUE;
CurrentVbo -= 1;
}
LastCluster = TRUE;
if (FirstLboOfCurrentRun != 0 ) {
DebugTrace( 0, Dbg, "Adding a run to the Mcb.\n", 0);
DebugTrace( 0, Dbg, " Vbo = %08lx.\n", FirstVboOfCurrentRun);
DebugTrace( 0, Dbg, " Lbo = %08lx.\n", FirstLboOfCurrentRun);
DebugTrace( 0, Dbg, " Length = %08lx.\n", CurrentVbo - FirstVboOfCurrentRun);
(VOID)FatAddMcbEntry( Vcb,
&FcbOrDcb->Mcb,
FirstVboOfCurrentRun,
FirstLboOfCurrentRun,
CurrentVbo - FirstVboOfCurrentRun );
Runs += 1;
}
//
// Being at the end of allocation, make sure we have found
// the Vbo. If we haven't, seeing as we checked VBO
// against AllocationSize, the real disk allocation is less
// than that of AllocationSize. This comes about when the
// real allocation is not yet known, and AllocaitonSize
// contains MAXULONG.
//
// KLUDGE! - If we were called by FatLookupFileAllocationSize
// Vbo is set to MAXULONG - 1, and AllocationSize to the lookup
// hint. Thus we merrily go along looking for a match that isn't
// there, but in the meantime building an Mcb. If this is
// the case, fill in AllocationSize and return.
//
if ( Vbo == MAXULONG - 1 ) {
*Allocated = FALSE;
FcbOrDcb->Header.AllocationSize.QuadPart = CurrentVbo;
DebugTrace( 0, Dbg, "New file allocation size = %08lx.\n", CurrentVbo);
try_return ( NOTHING );
}
//
// We will lie ever so slightly if we really terminated on the
// maximal byte of a file. It is really allocated.
//
if (Vbo >= CurrentVbo && !*EndOnMax) {
*Allocated = FALSE;
try_return ( NOTHING );
}
break;
//
// This is a continuation in the chain. If the run has a
// discontiguity at this point, update the Mcb, and if we are beyond
// the desired Vbo, this is the end of the run, so set LastCluster
// and exit the loop.
//
case FatClusterNext:
//
// This is the loop check. The Vbo must not be bigger than the size of
// the volume, and the Vbo must not have a) wrapped and b) not been at the
// very last cluster in the chain, for the case of the maximal file.
//
if ( CurrentVbo == 0 ||
(BytesOnVolume.HighPart == 0 && CurrentVbo > BytesOnVolume.LowPart)) {
FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
if ( PriorLbo + BytesPerCluster != CurrentLbo ) {
//
// Note that on the first time through the loop
// (FirstLboOfCurrentRun == 0), we don't add the
// run to the Mcb since it curresponds to the last
// run already stored in the Mcb.
//
if ( FirstLboOfCurrentRun != 0 ) {
DebugTrace( 0, Dbg, "Adding a run to the Mcb.\n", 0);
DebugTrace( 0, Dbg, " Vbo = %08lx.\n", FirstVboOfCurrentRun);
DebugTrace( 0, Dbg, " Lbo = %08lx.\n", FirstLboOfCurrentRun);
DebugTrace( 0, Dbg, " Length = %08lx.\n", CurrentVbo - FirstVboOfCurrentRun);
FatAddMcbEntry( Vcb,
&FcbOrDcb->Mcb,
FirstVboOfCurrentRun,
FirstLboOfCurrentRun,
CurrentVbo - FirstVboOfCurrentRun );
Runs += 1;
}
//
// Since we are at a run boundry, with CurrentLbo and
// CurrentVbo being the first cluster of the next run,
// we see if the run we just added encompases the desired
// Vbo, and if so exit. Otherwise we set up two new
// First*boOfCurrentRun, and continue.
//
if (CurrentVbo > Vbo) {
LastCluster = TRUE;
} else {
FirstVboOfCurrentRun = CurrentVbo;
FirstLboOfCurrentRun = CurrentLbo;
}
}
break;
default:
DebugTrace(0, Dbg, "Illegal Cluster Type.\n", FatEntry);
FatBugCheck( 0, 0, 0 );
break;
} // switch()
} // while()
//
// Load up the return parameters.
//
// On exit from the loop, Vbo still contains the desired Vbo, and
// CurrentVbo is the first byte after the run that contained the
// desired Vbo.
//
*Allocated = TRUE;
*Lbo = FirstLboOfCurrentRun + (Vbo - FirstVboOfCurrentRun);
*ByteCount = CurrentVbo - Vbo;
if (ARGUMENT_PRESENT(Index)) {
//
// Note that Runs only needs to be accurate with respect to where we
// ended. Since partial-lookup cases will occur without exclusive
// synchronization, the Mcb itself may be much bigger by now.
//
*Index = Runs - 1;
}
try_exit: NOTHING;
} finally {
DebugUnwind( FatLookupFileAllocation );
//
// We are done reading the Fat, so unpin the last page of fat
// that is hanging around
//
FatUnpinBcb( IrpContext, Context.Bcb );
DebugTrace(-1, Dbg, "FatLookupFileAllocation -> (VOID)\n", 0);
}
return;
}
VOID
FatAddFileAllocation (
IN PIRP_CONTEXT IrpContext,
IN PFCB FcbOrDcb,
IN PFILE_OBJECT FileObject OPTIONAL,
IN ULONG DesiredAllocationSize
)
/*++
Routine Description:
This routine adds additional allocation to the specified file/directory.
Additional allocation is added by appending clusters to the file/directory.
If the file already has a sufficient allocation then this procedure
is effectively a noop.
Arguments:
FcbOrDcb - Supplies the Fcb/Dcb of the file/directory being modified.
This parameter must not specify the root dcb.
FileObject - If supplied inform the cache manager of the change.
DesiredAllocationSize - Supplies the minimum size, in bytes, that we want
allocated to the file/directory.
--*/
{
PVCB Vcb;
LARGE_MCB NewMcb;
PLARGE_MCB McbToCleanup = NULL;
PDIRENT Dirent = NULL;
ULONG NewAllocation;
PBCB Bcb = NULL;
BOOLEAN UnwindWeAllocatedDiskSpace = FALSE;
BOOLEAN UnwindAllocationSizeSet = FALSE;
BOOLEAN UnwindCacheManagerInformed = FALSE;
BOOLEAN UnwindWeInitializedMcb = FALSE;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatAddFileAllocation\n", 0);
DebugTrace( 0, Dbg, " FcbOrDcb = %8lx\n", FcbOrDcb);
DebugTrace( 0, Dbg, " DesiredAllocationSize = %8lx\n", DesiredAllocationSize);
//
// If we haven't yet set the correct AllocationSize, do so.
//
if (FcbOrDcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT) {
FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
}
//
// Check for the benign case that the desired allocation is already
// within the allocation size.
//
if (DesiredAllocationSize <= FcbOrDcb->Header.AllocationSize.LowPart) {
DebugTrace(0, Dbg, "Desired size within current allocation.\n", 0);
DebugTrace(-1, Dbg, "FatAddFileAllocation -> (VOID)\n", 0);
return;
}
DebugTrace( 0, Dbg, "InitialAllocation = %08lx.\n", FcbOrDcb->Header.AllocationSize.LowPart);
//
// Get a chunk of disk space that will fullfill our needs. If there
// was no initial allocation, start from the hint in the Vcb, otherwise
// try to allocate from the cluster after the initial allocation.
//
// If there was no initial allocation to the file, we can just use the
// Mcb in the FcbOrDcb, otherwise we have to use a new one, and merge
// it to the one in the FcbOrDcb.
//
Vcb = FcbOrDcb->Vcb;
try {
if (FcbOrDcb->Header.AllocationSize.LowPart == 0) {
LBO FirstLboOfFile;
ASSERT( FcbOrDcb->FcbCondition == FcbGood );
FatGetDirentFromFcbOrDcb( IrpContext,
FcbOrDcb,
FALSE,
&Dirent,
&Bcb );
//
// Set this dirty right now since this call can fail.
//
FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );
FatAllocateDiskSpace( IrpContext,
Vcb,
0,
&DesiredAllocationSize,
FALSE,
&FcbOrDcb->Mcb );
UnwindWeAllocatedDiskSpace = TRUE;
McbToCleanup = &FcbOrDcb->Mcb;
//
// We have to update the dirent and FcbOrDcb copies of
// FirstClusterOfFile since before it was 0
//
FatLookupMcbEntry( FcbOrDcb->Vcb,
&FcbOrDcb->Mcb,
0,
&FirstLboOfFile,
(PULONG)NULL,
NULL );
DebugTrace( 0, Dbg, "First Lbo of file will be %08lx.\n", FirstLboOfFile );
FcbOrDcb->FirstClusterOfFile = FatGetIndexFromLbo( Vcb, FirstLboOfFile );
Dirent->FirstClusterOfFile = (USHORT)FcbOrDcb->FirstClusterOfFile;
if ( FatIsFat32(Vcb) ) {
Dirent->FirstClusterOfFileHi = (USHORT)(FcbOrDcb->FirstClusterOfFile >> 16);
}
//
// Note the size of the allocation we need to tell the cache manager about.
//
NewAllocation = DesiredAllocationSize;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -