/* * @implemented */ BOOLEAN NTAPI FsRtlAddMcbEntry(IN PMCB Mcb, IN VBN Vbn, IN LBN Lbn, IN ULONG SectorCount) { /* Call the newer function */ return FsRtlAddLargeMcbEntry(&Mcb-> DummyFieldThatSizesThisStructureCorrectly, (LONGLONG)Vbn, (LONGLONG)Lbn, (LONGLONG)SectorCount); }
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; }