📄 allocsup.c
字号:
Reference,
Lbn,
Len );
//
// Use try-finally for cleanup
//
try {
//
// We must safely establish a mapping and extend the metadata stream so that cached
// reads can occur on this new extent.
//
Fcb = Vcb->MetadataFcb;
UdfLockFcb( IrpContext, Fcb );
Result = UdfVmcbLbnToVbn( &Vcb->Vmcb,
Psn,
&Vsn,
&SectorCount );
if (Result) {
//
// If the mapping covers the extent, we can give this back.
//
if (BlocksFromSectors( Vcb, SectorCount ) >= BlocksFromBytes( Vcb, Len )) {
try_leave( NOTHING );
}
//
// It is a fatal error if the extent we are mapping is not wholly contained
// by an extent of Vsns in the Vmcb. This will indicate that some structure
// is trying to overlap another.
//
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
}
//
// Add the new mapping. We know that it is being added to the end of the stream.
//
UdfAddVmcbMapping( &Vcb->Vmcb,
Psn,
SectorsFromBytes( Vcb, Len ),
ExactEnd,
&Vsn,
&SectorCount );
UnwindAllocationSize = Fcb->AllocationSize.QuadPart;
UnwindExtension = TRUE;
Fcb->AllocationSize.QuadPart =
Fcb->FileSize.QuadPart =
Fcb->ValidDataLength.QuadPart = LlBytesFromSectors( Vcb, Vsn + SectorCount);
CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize );
UnwindExtension = FALSE;
//
// We do not need to purge the cache maps since the Vmcb will always be
// page aligned, and thus any reads will have filled it with valid data.
//
} finally {
if (UnwindExtension) {
ULONG FirstZappedVsn;
//
// Strip off the additional mappings we made.
//
Fcb->AllocationSize.QuadPart =
Fcb->FileSize.QuadPart =
Fcb->ValidDataLength.QuadPart = UnwindAllocationSize;
FirstZappedVsn = SectorsFromBytes( Vcb, UnwindAllocationSize );
UdfRemoveVmcbMapping( &Vcb->Vmcb,
FirstZappedVsn,
Vsn + SectorCount - FirstZappedVsn );
CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize );
}
if (Fcb) { UdfUnlockFcb( IrpContext, Fcb ); }
}
return Vsn;
}
//
// Local support routine.
//
PPCB
UdfCreatePcb (
IN ULONG NumberOfPartitions
)
/*++
Routine Description:
This routine creates a new Pcb of the indicated size.
Arguments:
NumberOfPartitions - Number of partitions this Pcb will describe
Return Value:
PPCB - the Pcb created
--*/
{
PPCB Pcb;
ULONG Size = sizeof(PCB) + sizeof(PARTITION)*NumberOfPartitions;
PAGED_CODE();
ASSERT( NumberOfPartitions );
ASSERT( NumberOfPartitions < MAXUSHORT );
Pcb = (PPCB) FsRtlAllocatePoolWithTag( UdfPagedPool,
Size,
TAG_PCB );
RtlZeroMemory( Pcb, Size );
Pcb->NodeTypeCode = UDFS_NTC_PCB;
Pcb->NodeByteSize = (USHORT) Size;
Pcb->Partitions = (USHORT)NumberOfPartitions;
return Pcb;
}
//
// Internal support routine
//
NTSTATUS
UdfLoadSparingTables(
PIRP_CONTEXT IrpContext,
PVCB Vcb,
PPCB Pcb,
ULONG Reference
)
/*++
Routine Description:
This routine reads the sparing tables for a partition and fills
in the sparing Mcb.
Arguments:
Vcb - the volume hosting the spared partition
Pcb - the partion block corresponding to the volume
Reference - the partition reference being pulled in
Return Value:
NTSTATUS according to whether the sparing tables were loaded
--*/
{
NTSTATUS Status;
ULONG SparingTable;
PULONG SectorBuffer;
ULONG Psn;
ULONG RemainingBytes;
ULONG ByteOffset;
ULONG TotalBytes;
BOOLEAN Complete;
PSPARING_TABLE_HEADER Header;
PSPARING_TABLE_ENTRY Entry;
PPARTITION Partition = &Pcb->Partition[Reference];
PPARTMAP_SPARABLE Map = Partition->Physical.SparingMap;
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_VCB( Vcb );
ASSERT( Map != NULL );
DebugTrace(( +1, Dbg, "UdfLoadSparingTables, Vcb %08x, PcbPartition %08x, Map @ %08x\n", Vcb, Partition, Map ));
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Map sez: PacketLen %u, NTables %u, TableSize %u\n",
Map->PacketLength,
Map->NumSparingTables,
Map->TableSize));
//
// Check that the sparale map appears sane. If there are no sparing tables that
// is pretty OK, and it'll wind up looking like a regular physical partition.
//
if (Map->NumSparingTables == 0) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, no sparing tables claimed!\n" ));
DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" ));
return STATUS_SUCCESS;
}
if (Map->NumSparingTables > sizeof(Map->TableLocation)/sizeof(ULONG)) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, too many claimed tables to fit! (max %u)\n",
sizeof(Map->TableLocation)/sizeof(ULONG)));
DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" ));
return STATUS_DISK_CORRUPT_ERROR;
}
if (Map->PacketLength != UDF_SPARING_PACKET_LENGTH) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, packet size is %u (not %u!\n",
Map->PacketLength,
UDF_SPARING_PACKET_LENGTH ));
DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" ));
return STATUS_DISK_CORRUPT_ERROR;
}
if (Map->TableSize < sizeof(SPARING_TABLE_HEADER) ||
(Map->TableSize - sizeof(SPARING_TABLE_HEADER)) % sizeof(SPARING_TABLE_ENTRY) != 0) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table size is too small or unaligned!\n" ));
DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" ));
return STATUS_DISK_CORRUPT_ERROR;
}
#ifdef UDF_SANITY
DebugTrace(( 0, Dbg, "UdfLoadSparingTables" ));
for (SparingTable = 0; SparingTable < Map->NumSparingTables; SparingTable++) {
DebugTrace(( 0, Dbg, ", Table %u @ %x", SparingTable, Map->TableLocation[SparingTable] ));
}
DebugTrace(( 0, Dbg, "\n" ));
#endif
//
// If a sparing mcb doesn't exist, manufacture one.
//
if (Pcb->SparingMcb == NULL) {
Pcb->SparingMcb = FsRtlAllocatePoolWithTag( PagedPool, sizeof(LARGE_MCB), TAG_SPARING_MCB );
FsRtlInitializeLargeMcb( Pcb->SparingMcb, PagedPool );
}
SectorBuffer = FsRtlAllocatePoolWithTag( PagedPool, PAGE_SIZE, TAG_NSR_FSD );
//
// Now loop across the sparing tables and pull the data in.
//
try {
for (Complete = FALSE, SparingTable = 0;
SparingTable < Map->NumSparingTables;
SparingTable++) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, loading sparing table %u!\n",
SparingTable ));
ByteOffset = 0;
TotalBytes = 0;
RemainingBytes = 0;
do {
if (RemainingBytes == 0) {
(VOID) UdfReadSectors( IrpContext,
BytesFromSectors( Vcb, Map->TableLocation[SparingTable] ) + ByteOffset,
SectorSize( Vcb ),
FALSE,
SectorBuffer,
Vcb->TargetDeviceObject );
//
// Verify the descriptor at the head of the sparing table. If it is not
// valid, we just break out for a chance at the next table, if any.
//
if (ByteOffset == 0) {
Header = (PSPARING_TABLE_HEADER) SectorBuffer;
if (!UdfVerifyDescriptor( IrpContext,
&Header->Destag,
0,
SectorSize( Vcb ),
Header->Destag.Lbn,
TRUE )) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify destag!\n",
SparingTable ));
break;
}
if (!UdfUdfIdentifierContained( &Header->RegID,
&UdfSparingTableIdentifier,
UDF_VERSION_150,
UDF_VERSION_RECOGNIZED,
OSCLASS_INVALID,
OSIDENTIFIER_INVALID)) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify regid!\n",
SparingTable ));
break;
}
//
// Calculate the total number bytes this map spans and check it against what
// we were told the sparing table sizes are.
//
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Sparing table %u has %u entries\n",
SparingTable,
Header->TableEntries ));
TotalBytes = sizeof(SPARING_TABLE_HEADER) + Header->TableEntries * sizeof(SPARING_TABLE_ENTRY);
if (Map->TableSize < TotalBytes) {
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table #ents %u overflows allocation!\n",
Header->TableEntries ));
break;
}
//
// So far so good, advance past the header.
//
ByteOffset = sizeof(SPARING_TABLE_HEADER);
Entry = Add2Ptr( SectorBuffer, sizeof(SPARING_TABLE_HEADER), PSPARING_TABLE_ENTRY );
} else {
//
// Pick up in the new sector.
//
Entry = (PSPARING_TABLE_ENTRY) SectorBuffer;
}
RemainingBytes = Min( SectorSize( Vcb ), TotalBytes - ByteOffset );
}
//
// Add the mapping. Since sparing tables are an Lbn->Psn mapping,
// very odd, and I want to simplify things by putting the sparing
// in right at IO dispatch, translate this to a Psn->Psn mapping.
//
if (Entry->Original != UDF_SPARING_AVALIABLE &&
Entry->Original != UDF_SPARING_DEFECTIVE) {
Psn = Partition->Physical.Start + SectorsFromBlocks( Vcb, Entry->Original );
DebugTrace(( 0, Dbg, "UdfLoadSparingTables, mapping from Psn %x (Lbn %x) -> Psn %x\n",
Psn,
Entry->Original,
Entry->Mapped ));
FsRtlAddLargeMcbEntry( Pcb->SparingMcb,
Psn,
Entry->Mapped,
UDF_SPARING_PACKET_LENGTH );
}
//
// Advance to the next, and drop out if we've hit the end.
//
ByteOffset += sizeof(SPARING_TABLE_ENTRY);
RemainingBytes -= sizeof(SPARING_TABLE_ENTRY);
Entry++;
} while ( ByteOffset < TotalBytes );
}
} finally {
DebugUnwind( UdfLoadSparingTables );
UdfFreePool( &SectorBuffer );
}
DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" ));
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -