Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

allocsup.c File Reference

#include "UdfProcs.h"

Go to the source code of this file.

Defines

#define BugCheckFileId   (UDFS_BUG_CHECK_ALLOCSUP)
#define Dbg   (UDFS_DEBUG_LEVEL_ALLOCSUP)

Functions

PPCB UdfCreatePcb (IN ULONG NumberOfPartitions)
NTSTATUS UdfLoadSparingTables (PIRP_CONTEXT IrpContext, PVCB Vcb, PPCB Pcb, ULONG Reference)
BOOLEAN UdfLookupAllocation (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN LONGLONG FileOffset, OUT PLONGLONG DiskOffset, OUT PULONG ByteCount)
VOID UdfDeletePcb (IN PPCB Pcb)
NTSTATUS UdfInitializePcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN OUT PPCB *Pcb, IN PNSR_LVOL LVD)
VOID UdfAddToPcb (IN PPCB Pcb, IN PNSR_PART PartitionDescriptor)
NTSTATUS UdfCompletePcb (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PPCB Pcb)
BOOLEAN UdfEquivalentPcb (IN PIRP_CONTEXT IrpContext, IN PPCB Pcb1, IN PPCB Pcb2)
ULONG UdfLookupPsnOfExtent (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT Reference, IN ULONG Lbn, IN ULONG Len)
ULONG UdfLookupMetaVsnOfExtent (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN USHORT Reference, IN ULONG Lbn, IN ULONG Len, IN BOOLEAN ExactEnd)


Define Documentation

#define BugCheckFileId   (UDFS_BUG_CHECK_ALLOCSUP)
 

Definition at line 29 of file allocsup.c.

#define Dbg   (UDFS_DEBUG_LEVEL_ALLOCSUP)
 

Definition at line 35 of file allocsup.c.


Function Documentation

VOID UdfAddToPcb IN PPCB  Pcb,
IN PNSR_PART  PartitionDescriptor
 

Definition at line 724 of file allocsup.c.

References ASSERT, ASSERT_PCB, Dbg, DebugTrace, FALSE, PAGED_CODE, Physical, PNSR_PART, PNSR_VD_GENERIC, UdfStoreVolumeDescriptorIfPrevailing(), USHORT, and Virtual.

Referenced by UdfFindVolumeDescriptors().

00731 : 00732 00733 This routine possibly adds a partition descriptor into a Pcb if it 00734 turns out to be of higher precendence than a descriptor already 00735 present. Used in building a Pcb already initialized in preperation 00736 for UdfCompletePcb. 00737 00738 Arguments: 00739 00740 Vcb - Vcb of the volume the Pcb describes 00741 00742 Pcb - Pcb being filled in 00743 00744 Return Value: 00745 00746 None. An old partition descriptor may be returned in the input field. 00747 00748 --*/ 00749 00750 { 00751 USHORT Reference; 00752 00753 PAGED_CODE(); 00754 00755 // 00756 // Check inputs 00757 // 00758 00759 ASSERT_PCB( Pcb ); 00760 ASSERT( PartitionDescriptor ); 00761 00762 for (Reference = 0; 00763 Reference < Pcb->Partitions; 00764 Reference++) { 00765 00766 DebugTrace(( 0, Dbg, "UdfAddToPcb, considering partition reference %d (type %d)\n", (ULONG)Reference, Pcb->Partition[Reference].Type)); 00767 00768 switch (Pcb->Partition[Reference].Type) { 00769 00770 case Physical: 00771 00772 // 00773 // Now possibly store this descriptor in the Pcb if it is 00774 // the partition number for this partition reference. 00775 // 00776 00777 if (Pcb->Partition[Reference].Physical.PartitionNumber == PartitionDescriptor->Number) { 00778 00779 // 00780 // It seems to be legal (if questionable) for multiple partition maps to reference 00781 // the same partition descriptor. So we make a copy of the descriptor for each 00782 // referencing partitionmap to make life easier when it comes to freeing it. 00783 // 00784 00785 UdfStoreVolumeDescriptorIfPrevailing( (PNSR_VD_GENERIC *) &Pcb->Partition[Reference].Physical.PartitionDescriptor, 00786 (PNSR_VD_GENERIC) PartitionDescriptor ); 00787 } 00788 00789 break; 00790 00791 case Virtual: 00792 break; 00793 00794 default: 00795 00796 ASSERT(FALSE); 00797 break; 00798 } 00799 } 00800 }

NTSTATUS UdfCompletePcb IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb,
IN PPCB  Pcb
 

Definition at line 804 of file allocsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, ASSERT_PCB, ASSERT_VCB, Dbg, DebugTrace, FALSE, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Physical, Status, UdfFreePool(), UdfLoadSparingTables(), and Virtual.

Referenced by UdfMountVolume(), and UdfVerifyVolume().

00812 : 00813 00814 This routine completes initialization of a Pcb which has been filled 00815 in with partition descriptors. Initialization-time data such as the 00816 physical partition descriptors will be returned to the system. 00817 00818 Arguments: 00819 00820 Vcb - Vcb of the volume the Pcb describes 00821 00822 Pcb - Pcb being completed 00823 00824 Return Value: 00825 00826 NTSTATUS according to whether intialization completion was succesful 00827 00828 --*/ 00829 00830 { 00831 ULONG Reference; 00832 00833 NTSTATUS Status; 00834 00835 PAGED_CODE(); 00836 00837 // 00838 // Check inputs 00839 // 00840 00841 ASSERT_IRP_CONTEXT( IrpContext ); 00842 ASSERT_VCB( Vcb ); 00843 ASSERT_PCB( Pcb ); 00844 00845 DebugTrace(( +1, Dbg, "UdfCompletePcb, Vcb %08x Pcb %08x\n", Vcb, Pcb )); 00846 00847 // 00848 // Complete intialization all physical partitions 00849 // 00850 00851 for (Reference = 0; 00852 Reference < Pcb->Partitions; 00853 Reference++) { 00854 00855 DebugTrace(( 0, Dbg, "UdfCompletePcb, Examining Ref %u (type %u)!\n", Reference, Pcb->Partition[Reference].Type)); 00856 00857 switch (Pcb->Partition[Reference].Type) { 00858 00859 case Physical: 00860 00861 if (Pcb->Partition[Reference].Physical.PartitionDescriptor == NULL) { 00862 00863 DebugTrace(( 0, Dbg, 00864 "UdfCompletePcb, ... but didn't find Partition# %u!\n", 00865 Pcb->Partition[Reference].Physical.PartitionNumber )); 00866 00867 DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_DISK_CORRUPT_ERROR\n" )); 00868 00869 return STATUS_DISK_CORRUPT_ERROR; 00870 } 00871 00872 Pcb->Partition[Reference].Physical.Start = 00873 Pcb->Partition[Reference].Physical.PartitionDescriptor->Start; 00874 Pcb->Partition[Reference].Physical.Length = 00875 Pcb->Partition[Reference].Physical.PartitionDescriptor->Length; 00876 00877 00878 // 00879 // Retrieve the sparing information at this point if appropriate. 00880 // We have to do this when we can map logical -> physical blocks. 00881 // 00882 00883 if (Pcb->Partition[Reference].Physical.SparingMap) { 00884 00885 Status = UdfLoadSparingTables( IrpContext, 00886 Vcb, 00887 Pcb, 00888 Reference ); 00889 00890 if (!NT_SUCCESS( Status )) { 00891 00892 DebugTrace(( -1, Dbg, 00893 "UdfCompletePcb -> %08x\n", Status )); 00894 return Status; 00895 } 00896 } 00897 00898 // 00899 // We will not need the descriptor or sparing map anymore, so drop them. 00900 // 00901 00902 UdfFreePool( &Pcb->Partition[Reference].Physical.PartitionDescriptor ); 00903 UdfFreePool( &Pcb->Partition[Reference].Physical.SparingMap ); 00904 break; 00905 00906 case Virtual: 00907 break; 00908 00909 default: 00910 00911 ASSERT(FALSE); 00912 break; 00913 } 00914 } 00915 00916 DebugTrace(( -1, Dbg, "UdfCompletePcb -> STATUS_SUCCESS\n" )); 00917 00918 return STATUS_SUCCESS; 00919 }

PPCB UdfCreatePcb IN ULONG  NumberOfPartitions  ) 
 

Definition at line 1357 of file allocsup.c.

References ASSERT, FsRtlAllocatePoolWithTag, _PCB::NodeByteSize, _PCB::NodeTypeCode, PAGED_CODE, _PCB::Partitions, PCB, Size, TAG_PCB, UdfPagedPool, UDFS_NTC_PCB, and USHORT.

Referenced by UdfInitializePcb().

01363 : 01364 01365 This routine creates a new Pcb of the indicated size. 01366 01367 Arguments: 01368 01369 NumberOfPartitions - Number of partitions this Pcb will describe 01370 01371 Return Value: 01372 01373 PPCB - the Pcb created 01374 01375 --*/ 01376 01377 { 01378 PPCB Pcb; 01379 ULONG Size = sizeof(PCB) + sizeof(PARTITION)*NumberOfPartitions; 01380 01381 PAGED_CODE(); 01382 01383 ASSERT( NumberOfPartitions ); 01384 ASSERT( NumberOfPartitions < MAXUSHORT ); 01385 01386 Pcb = (PPCB) FsRtlAllocatePoolWithTag( UdfPagedPool, 01387 Size, 01388 TAG_PCB ); 01389 01390 RtlZeroMemory( Pcb, Size ); 01391 01392 Pcb->NodeTypeCode = UDFS_NTC_PCB; 01393 Pcb->NodeByteSize = (USHORT) Size; 01394 01395 Pcb->Partitions = (USHORT)NumberOfPartitions; 01396 01397 return Pcb; 01398 }

VOID UdfDeletePcb IN PPCB  Pcb  ) 
 

Definition at line 309 of file allocsup.c.

References ASSERT, ExFreePool(), FALSE, FsRtlUninitializeLargeMcb(), Physical, PPARTITION, UdfFreePool(), Uninitialized, and Virtual.

Referenced by UdfDeleteVcb(), UdfInitializePcb(), UdfMountVolume(), and UdfVerifyVolume().

00315 : 00316 00317 This routine deallocates a Pcb and all ancilliary structures. 00318 00319 Arguments: 00320 00321 Pcb - Pcb being deleted 00322 00323 Return Value: 00324 00325 None 00326 00327 --*/ 00328 00329 { 00330 PPARTITION Partition; 00331 00332 if (Pcb->SparingMcb) { 00333 00334 FsRtlUninitializeLargeMcb( Pcb->SparingMcb ); 00335 UdfFreePool( &Pcb->SparingMcb ); 00336 } 00337 00338 for (Partition = Pcb->Partition; 00339 Partition < &Pcb->Partition[Pcb->Partitions]; 00340 Partition++) { 00341 00342 switch (Partition->Type) { 00343 00344 case Physical: 00345 00346 UdfFreePool( &Partition->Physical.PartitionDescriptor ); 00347 UdfFreePool( &Partition->Physical.SparingMap ); 00348 00349 break; 00350 00351 case Virtual: 00352 case Uninitialized: 00353 break; 00354 00355 default: 00356 00357 ASSERT( FALSE ); 00358 break; 00359 } 00360 } 00361 00362 ExFreePool( Pcb ); 00363 }

BOOLEAN UdfEquivalentPcb IN PIRP_CONTEXT  IrpContext,
IN PPCB  Pcb1,
IN PPCB  Pcb2
 

Definition at line 923 of file allocsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, FALSE, Index, PAGED_CODE, Physical, TRUE, and Virtual.

Referenced by UdfVerifyVolume().

00931 : 00932 00933 This routine compares two completed Pcbs to see if they appear equivalent. 00934 00935 Arguments: 00936 00937 Pcb1 - Pcb being compared 00938 00939 Pcb2 - Pcb being compared 00940 00941 Return Value: 00942 00943 BOOLEAN according to whether they are equivalent (TRUE, else FALSE) 00944 00945 --*/ 00946 00947 { 00948 ULONG Index; 00949 00950 PAGED_CODE(); 00951 00952 // 00953 // Check input. 00954 // 00955 00956 ASSERT_IRP_CONTEXT( IrpContext ); 00957 00958 if (Pcb1->Partitions != Pcb2->Partitions) { 00959 00960 return FALSE; 00961 } 00962 00963 for (Index = 0; 00964 Index < Pcb1->Partitions; 00965 Index++) { 00966 00967 // 00968 // First check that the partitions are of the same type. 00969 // 00970 00971 if (Pcb1->Partition[Index].Type != Pcb2->Partition[Index].Type) { 00972 00973 return FALSE; 00974 } 00975 00976 // 00977 // Now the map content must be the same ... 00978 // 00979 00980 switch (Pcb1->Partition[Index].Type) { 00981 00982 case Physical: 00983 00984 if (Pcb1->Partition[Index].Physical.PartitionNumber != Pcb2->Partition[Index].Physical.PartitionNumber || 00985 Pcb1->Partition[Index].Physical.Length != Pcb2->Partition[Index].Physical.Length || 00986 Pcb1->Partition[Index].Physical.Start != Pcb2->Partition[Index].Physical.Start) { 00987 00988 return FALSE; 00989 } 00990 break; 00991 00992 case Virtual: 00993 00994 if (Pcb1->Partition[Index].Virtual.RelatedReference != Pcb2->Partition[Index].Virtual.RelatedReference) { 00995 00996 return FALSE; 00997 } 00998 break; 00999 01000 default: 01001 01002 ASSERT( FALSE); 01003 return FALSE; 01004 break; 01005 } 01006 } 01007 01008 // 01009 // All map elements were equivalent. 01010 // 01011 01012 return TRUE; 01013 }

NTSTATUS UdfInitializePcb IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb,
IN OUT PPCB Pcb,
IN PNSR_LVOL  LVD
 

Definition at line 367 of file allocsup.c.

References Add2Ptr, ASSERT_OPTIONAL_PCB, Dbg, DebugTrace, FALSE, FlagOn, FsRtlAllocatePoolWithTag, ISONsrLvolSize, _PARTMAP_UDF_GENERIC::Length, NTSTATUS(), NULL, PAGED_CODE, PagedPool, _PARTMAP_UDF_GENERIC::PartID, PARTITION, PARTMAP_PHYSICAL::Partition, _PARTMAP_VIRTUAL::Partition, _PARTMAP_SPARABLE::Partition, _tagPARTITION::PartitionNumber, PARTMAP_SPARABLE, PARTMAP_TYPE_PHYSICAL, PARTMAP_TYPE_PROXY, PCB_FLAG_PHYSICAL_PARTITION, PCB_FLAG_SPARABLE_PARTITION, PCB_FLAG_VIRTUAL_PARTITION, Physical, PNSR_LVOL, PPARTMAP_PHYSICAL, PPARTMAP_SPARABLE, PPARTMAP_UDF_GENERIC, PPARTMAP_VIRTUAL, SetFlag, Status, TAG_NSR_FSD, TRUE, _PARTMAP_UDF_GENERIC::Type, UDF_VERSION_150, UDF_VERSION_RECOGNIZED, UdfCreatePcb(), UdfDeletePcb(), UdfDomainIdentifierContained(), UdfSparablePartitionDomainIdentifier, UdfVirtualPartitionDomainIdentifier, USHORT, Virtual, PARTMAP_PHYSICAL::VolSetSeq, and _PARTMAP_SPARABLE::VolSetSeq.

Referenced by UdfFindVolumeDescriptors().

00376 : 00377 00378 This routine walks through the partition map of a Logical Volume Descriptor 00379 and builds an intializing Pcb from it. The Pcb will be ready to be used 00380 in searching for the partition descriptors of a volume. 00381 00382 Arguments: 00383 00384 Vcb - The volume this Pcb will pertain to 00385 00386 Pcb - Caller's pointer to the Pcb 00387 00388 LVD - The Logical Volume Descriptor being used 00389 00390 Return Value: 00391 00392 STATUS_SUCCESS if the partition map is good and the Pcb is built 00393 00394 STATUS_DISK_CORRUPT_ERROR if corrupt maps are found 00395 00396 STATUS_UNRECOGNIZED_VOLUME if noncompliant maps are found 00397 00398 --*/ 00399 00400 { 00401 PPARTMAP_UDF_GENERIC Map; 00402 PPARTITION Partition; 00403 00404 BOOLEAN Found; 00405 00406 PAGED_CODE(); 00407 00408 // 00409 // Check the input parameters 00410 // 00411 00412 ASSERT_OPTIONAL_PCB( *Pcb ); 00413 00414 DebugTrace(( +1, Dbg, 00415 "UdfInitializePcb, Lvd %08x\n", 00416 LVD )); 00417 00418 // 00419 // Delete a pre-existing (partially initialized from a failed 00420 // crawl of a VDS) Pcb. 00421 // 00422 00423 if (*Pcb != NULL) { 00424 00425 UdfDeletePcb( *Pcb ); 00426 *Pcb = NULL; 00427 } 00428 00429 *Pcb = UdfCreatePcb( LVD->MapTableCount ); 00430 00431 // 00432 // Walk the table of partition maps intializing the Pcb for the descriptor 00433 // initialization pass. 00434 // 00435 00436 for (Map = (PPARTMAP_UDF_GENERIC) LVD->MapTable, 00437 Partition = (*Pcb)->Partition; 00438 00439 Partition < &(*Pcb)->Partition[(*Pcb)->Partitions]; 00440 00441 Map = Add2Ptr( Map, Map->Length, PPARTMAP_UDF_GENERIC ), 00442 Partition++) { 00443 00444 // 00445 // Now check that this LVD can actually contain this map entry. First check that 00446 // the descriptor can contain the first few fields, then check that it can hold 00447 // all of the bytes claimed by the descriptor. 00448 // 00449 00450 if (Add2Ptr( Map, sizeof( PARTMAP_GENERIC ), PCHAR ) > Add2Ptr( LVD, ISONsrLvolSize( LVD ), PCHAR ) || 00451 Add2Ptr( Map, Map->Length, PCHAR ) > Add2Ptr( LVD, ISONsrLvolSize( LVD ), PCHAR )) { 00452 00453 DebugTrace(( 0, Dbg, 00454 "UdfInitializePcb, map at +%04x beyond Lvd size %04x\n", 00455 (PCHAR) Map - (PCHAR) LVD, 00456 ISONsrLvolSize( LVD ))); 00457 00458 DebugTrace(( -1, Dbg, 00459 "UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" )); 00460 00461 return STATUS_DISK_CORRUPT_ERROR; 00462 } 00463 00464 // 00465 // Now load up this map entry. 00466 // 00467 00468 switch (Map->Type) { 00469 00470 case PARTMAP_TYPE_PHYSICAL: 00471 00472 { 00473 PPARTMAP_PHYSICAL MapPhysical = (PPARTMAP_PHYSICAL) Map; 00474 00475 // 00476 // Type 1 - Physical Partition 00477 // 00478 00479 DebugTrace(( 0, Dbg, 00480 "UdfInitializePcb, map reference %02x is Physical (Partition # %08x)\n", 00481 (Partition - (*Pcb)->Partition)/sizeof(PARTITION), 00482 MapPhysical->Partition )); 00483 00484 // 00485 // It must be the case that the volume the partition is on is the first 00486 // one since we only do single disc UDF. This will have already been 00487 // checked by the caller. 00488 // 00489 00490 if (MapPhysical->VolSetSeq > 1) { 00491 00492 DebugTrace(( 0, Dbg, 00493 "UdfInitializePcb, ... but physical partition resides on volume set volume # %08x (> 1)!\n", 00494 MapPhysical->VolSetSeq )); 00495 00496 DebugTrace(( -1, Dbg, 00497 "UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" )); 00498 00499 return STATUS_DISK_CORRUPT_ERROR; 00500 } 00501 00502 SetFlag( (*Pcb)->Flags, PCB_FLAG_PHYSICAL_PARTITION ); 00503 Partition->Type = Physical; 00504 Partition->Physical.PartitionNumber = MapPhysical->Partition; 00505 } 00506 00507 break; 00508 00509 case PARTMAP_TYPE_PROXY: 00510 00511 // 00512 // Type 2 - a Proxy Partition, something not explicitly physical. 00513 // 00514 00515 DebugTrace(( 0, Dbg, 00516 "UdfInitializePcb, map reference %02x is a proxy\n", 00517 (Partition - (*Pcb)->Partition)/sizeof(PARTITION))); 00518 00519 // 00520 // Handle the various types of proxy partitions we recognize 00521 // 00522 00523 if (UdfDomainIdentifierContained( &Map->PartID, 00524 &UdfVirtualPartitionDomainIdentifier, 00525 UDF_VERSION_150, 00526 UDF_VERSION_RECOGNIZED )) { 00527 00528 { 00529 PPARTMAP_VIRTUAL MapVirtual = (PPARTMAP_VIRTUAL) Map; 00530 00531 // 00532 // Only one of these guys can exist, since there can be only one VAT per media surface. 00533 // 00534 00535 if (FlagOn( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION )) { 00536 00537 DebugTrace(( 0, Dbg, 00538 "UdfInitializePcb, ... but this is a second virtual partition!?!!\n" )); 00539 00540 DebugTrace(( -1, Dbg, 00541 "UdfInitializePcb -> STATUS_UNCRECOGNIZED_VOLUME\n" )); 00542 00543 return STATUS_UNRECOGNIZED_VOLUME; 00544 } 00545 00546 DebugTrace(( 0, Dbg, 00547 "UdfInitializePcb, ... Virtual (Partition # %08x)\n", 00548 MapVirtual->Partition )); 00549 00550 SetFlag( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION ); 00551 Partition->Type = Virtual; 00552 00553 // 00554 // We will convert the partition number to a partition reference 00555 // before returning. 00556 // 00557 00558 Partition->Virtual.RelatedReference = MapVirtual->Partition; 00559 } 00560 00561 } else if (UdfDomainIdentifierContained( &Map->PartID, 00562 &UdfSparablePartitionDomainIdentifier, 00563 UDF_VERSION_150, 00564 UDF_VERSION_RECOGNIZED )) { 00565 00566 { 00567 NTSTATUS Status; 00568 PPARTMAP_SPARABLE MapSparable = (PPARTMAP_SPARABLE) Map; 00569 00570 // 00571 // It must be the case that the volume the partition is on is the first 00572 // one since we only do single disc UDF. This will have already been 00573 // checked by the caller. 00574 // 00575 00576 if (MapSparable->VolSetSeq > 1) { 00577 00578 DebugTrace(( 0, Dbg, 00579 "UdfInitializePcb, ... but sparable partition resides on volume set volume # %08x (> 1)!\n", 00580 MapSparable->VolSetSeq )); 00581 00582 DebugTrace(( -1, Dbg, 00583 "UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" )); 00584 00585 return STATUS_DISK_CORRUPT_ERROR; 00586 } 00587 00588 DebugTrace(( 0, Dbg, 00589 "UdfInitializePcb, ... Sparable (Partition # %08x)\n", 00590 MapSparable->Partition )); 00591 00592 // 00593 // We pretend that sparable partitions are basically the same as 00594 // physical partitions. Since we are not r/w (and will never be 00595 // on media that requires host-based sparing in any case), this 00596 // is a good simplification. 00597 // 00598 00599 SetFlag( (*Pcb)->Flags, PCB_FLAG_SPARABLE_PARTITION ); 00600 Partition->Type = Physical; 00601 Partition->Physical.PartitionNumber = MapSparable->Partition; 00602 00603 // 00604 // Save this map for use when the partition descriptor is found. 00605 // We can't load the sparing table at this time because we have 00606 // to turn the Lbn->Psn mapping into a Psn->Psn mapping. UDF 00607 // believes that the way sparing will be used in concert with 00608 // the Lbn->Psn mapping engine (like UdfLookupPsnOfExtent). 00609 // 00610 // Unfortunately, this would be a bit painful at this time. 00611 // The users of UdfLookupPsnOfExtent would need to iterate 00612 // over a new interface (not so bad) but the Vmcb package 00613 // would need to be turned inside out so that it didn't do 00614 // the page-filling alignment of blocks in the metadata 00615 // stream - instead, UdfLookupMetaVsnOfExtent would need to 00616 // do this itself. I choose to lay the sparing engine into 00617 // the read path and raw sector read engine instead. 00618 // 00619 00620 Partition->Physical.SparingMap = FsRtlAllocatePoolWithTag( PagedPool, 00621 sizeof(PARTMAP_SPARABLE), 00622 TAG_NSR_FSD); 00623 RtlCopyMemory( Partition->Physical.SparingMap, 00624 MapSparable, 00625 sizeof(PARTMAP_SPARABLE)); 00626 } 00627 00628 } else { 00629 00630 DebugTrace(( 0, Dbg, 00631 "UdfInitializePcb, ... but we don't recognize this proxy!\n" )); 00632 00633 DebugTrace(( -1, Dbg, 00634 "UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" )); 00635 00636 return STATUS_UNRECOGNIZED_VOLUME; 00637 } 00638 00639 break; 00640 00641 default: 00642 00643 DebugTrace(( 0, Dbg, 00644 "UdfInitializePcb, map reference %02x is of unknown type %02x\n", 00645 Map->Type )); 00646 00647 DebugTrace(( -1, Dbg, 00648 "UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" )); 00649 00650 return STATUS_UNRECOGNIZED_VOLUME; 00651 break; 00652 } 00653 } 00654 00655 if (!FlagOn( (*Pcb)->Flags, PCB_FLAG_PHYSICAL_PARTITION | PCB_FLAG_SPARABLE_PARTITION )) { 00656 00657 DebugTrace(( 0, Dbg, 00658 "UdfInitializePcb, no physical partition seen on this logical volume!\n" )); 00659 00660 DebugTrace(( -1, Dbg, 00661 "UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" )); 00662 00663 return STATUS_UNRECOGNIZED_VOLUME; 00664 } 00665 00666 if (FlagOn( (*Pcb)->Flags, PCB_FLAG_VIRTUAL_PARTITION )) { 00667 00668 PPARTITION Host; 00669 00670 // 00671 // Confirm the validity of any type 2 virtual maps on this volume 00672 // and convert partition numbers to partition references that will 00673 // immediately index an element of the Pcb. 00674 // 00675 00676 for (Partition = (*Pcb)->Partition; 00677 Partition < &(*Pcb)->Partition[(*Pcb)->Partitions]; 00678 Partition++) { 00679 00680 if (Partition->Type == Virtual) { 00681 00682 // 00683 // Go find the partition this thing is talking about 00684 // 00685 00686 Found = FALSE; 00687 00688 for (Host = (*Pcb)->Partition; 00689 Host < &(*Pcb)->Partition[(*Pcb)->Partitions]; 00690 Host++) { 00691 00692 if (Host->Type == Physical && 00693 Host->Physical.PartitionNumber == 00694 Partition->Virtual.RelatedReference) { 00695 00696 Partition->Virtual.RelatedReference = 00697 (USHORT)(Host - (*Pcb)->Partition)/sizeof(PARTITION); 00698 Found = TRUE; 00699 break; 00700 } 00701 } 00702 00703 // 00704 // Failure to find a physical partition for this virtual guy 00705 // is not a good sign. 00706 // 00707 00708 if (!Found) { 00709 00710 return STATUS_DISK_CORRUPT_ERROR; 00711 } 00712 } 00713 } 00714 } 00715 00716 DebugTrace(( -1, Dbg, 00717 "UdfInitializePcb -> STATUS_SUCCESS\n" )); 00718 00719 return STATUS_SUCCESS; 00720 }

NTSTATUS UdfLoadSparingTables PIRP_CONTEXT  IrpContext,
PVCB  Vcb,
PPCB  Pcb,
ULONG  Reference
 

Definition at line 1406 of file allocsup.c.

References Add2Ptr, ASSERT, ASSERT_IRP_CONTEXT, ASSERT_VCB, BytesFromSectors, Dbg, DebugTrace, DebugUnwind, FALSE, FsRtlAddLargeMcbEntry(), FsRtlAllocatePoolWithTag, FsRtlInitializeLargeMcb(), Header, _SPARING_TABLE_ENTRY::Mapped, Min, NTSTATUS(), NULL, _PARTMAP_SPARABLE::NumSparingTables, _SPARING_TABLE_ENTRY::Original, OSCLASS_INVALID, OSIDENTIFIER_INVALID, _PARTMAP_SPARABLE::PacketLength, PAGE_SIZE, PagedPool, _PCB::Partition, PSPARING_TABLE_ENTRY, PSPARING_TABLE_HEADER, SectorsFromBlocks, SectorSize, SPARING_TABLE_ENTRY, SPARING_TABLE_HEADER, _PCB::SparingMcb, Status, _PARTMAP_SPARABLE::TableLocation, _PARTMAP_SPARABLE::TableSize, TAG_NSR_FSD, TAG_SPARING_MCB, _VCB::TargetDeviceObject, TRUE, UDF_SPARING_AVALIABLE, UDF_SPARING_DEFECTIVE, UDF_SPARING_PACKET_LENGTH, UDF_VERSION_150, UDF_VERSION_RECOGNIZED, UdfFreePool(), UdfLoadSparingTables(), UdfReadSectors(), UdfSparingTableIdentifier, UdfUdfIdentifierContained(), UdfVerifyDescriptor(), and VOID().

Referenced by UdfCompletePcb(), and UdfLoadSparingTables().

01415 : 01416 01417 This routine reads the sparing tables for a partition and fills 01418 in the sparing Mcb. 01419 01420 Arguments: 01421 01422 Vcb - the volume hosting the spared partition 01423 01424 Pcb - the partion block corresponding to the volume 01425 01426 Reference - the partition reference being pulled in 01427 01428 Return Value: 01429 01430 NTSTATUS according to whether the sparing tables were loaded 01431 01432 --*/ 01433 01434 { 01435 NTSTATUS Status; 01436 01437 ULONG SparingTable; 01438 PULONG SectorBuffer; 01439 ULONG Psn; 01440 01441 ULONG RemainingBytes; 01442 ULONG ByteOffset; 01443 ULONG TotalBytes; 01444 01445 BOOLEAN Complete; 01446 01447 PSPARING_TABLE_HEADER Header; 01448 PSPARING_TABLE_ENTRY Entry; 01449 01450 PPARTITION Partition = &Pcb->Partition[Reference]; 01451 PPARTMAP_SPARABLE Map = Partition->Physical.SparingMap; 01452 01453 ASSERT_IRP_CONTEXT( IrpContext ); 01454 ASSERT_VCB( Vcb ); 01455 01456 ASSERT( Map != NULL ); 01457 01458 DebugTrace(( +1, Dbg, "UdfLoadSparingTables, Vcb %08x, PcbPartition %08x, Map @ %08x\n", Vcb, Partition, Map )); 01459 01460 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Map sez: PacketLen %u, NTables %u, TableSize %u\n", 01461 Map->PacketLength, 01462 Map->NumSparingTables, 01463 Map->TableSize)); 01464 01465 01466 // 01467 // Check that the sparale map appears sane. If there are no sparing tables that 01468 // is pretty OK, and it'll wind up looking like a regular physical partition. 01469 // 01470 01471 if (Map->NumSparingTables == 0) { 01472 01473 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, no sparing tables claimed!\n" )); 01474 DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" )); 01475 return STATUS_SUCCESS; 01476 } 01477 01478 if (Map->NumSparingTables > sizeof(Map->TableLocation)/sizeof(ULONG)) { 01479 01480 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, too many claimed tables to fit! (max %u)\n", 01481 sizeof(Map->TableLocation)/sizeof(ULONG))); 01482 DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); 01483 return STATUS_DISK_CORRUPT_ERROR; 01484 } 01485 01486 if (Map->PacketLength != UDF_SPARING_PACKET_LENGTH) { 01487 01488 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, packet size is %u (not %u!\n", 01489 Map->PacketLength, 01490 UDF_SPARING_PACKET_LENGTH )); 01491 DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); 01492 return STATUS_DISK_CORRUPT_ERROR; 01493 } 01494 01495 if (Map->TableSize < sizeof(SPARING_TABLE_HEADER) || 01496 (Map->TableSize - sizeof(SPARING_TABLE_HEADER)) % sizeof(SPARING_TABLE_ENTRY) != 0) { 01497 01498 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table size is too small or unaligned!\n" )); 01499 DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" )); 01500 return STATUS_DISK_CORRUPT_ERROR; 01501 } 01502 01503 #ifdef UDF_SANITY 01504 DebugTrace(( 0, Dbg, "UdfLoadSparingTables" )); 01505 for (SparingTable = 0; SparingTable < Map->NumSparingTables; SparingTable++) { 01506 01507 DebugTrace(( 0, Dbg, ", Table %u @ %x", SparingTable, Map->TableLocation[SparingTable] )); 01508 } 01509 DebugTrace(( 0, Dbg, "\n" )); 01510 #endif 01511 01512 // 01513 // If a sparing mcb doesn't exist, manufacture one. 01514 // 01515 01516 if (Pcb->SparingMcb == NULL) { 01517 01518 Pcb->SparingMcb = FsRtlAllocatePoolWithTag( PagedPool, sizeof(LARGE_MCB), TAG_SPARING_MCB ); 01519 FsRtlInitializeLargeMcb( Pcb->SparingMcb, PagedPool ); 01520 } 01521 01522 SectorBuffer = FsRtlAllocatePoolWithTag( PagedPool, PAGE_SIZE, TAG_NSR_FSD ); 01523 01524 // 01525 // Now loop across the sparing tables and pull the data in. 01526 // 01527 01528 try { 01529 01530 for (Complete = FALSE, SparingTable = 0; 01531 01532 SparingTable < Map->NumSparingTables; 01533 01534 SparingTable++) { 01535 01536 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, loading sparing table %u!\n", 01537 SparingTable )); 01538 01539 ByteOffset = 0; 01540 TotalBytes = 0; 01541 RemainingBytes = 0; 01542 01543 do { 01544 01545 if (RemainingBytes == 0) { 01546 01547 (VOID) UdfReadSectors( IrpContext, 01548 BytesFromSectors( Vcb, Map->TableLocation[SparingTable] ) + ByteOffset, 01549 SectorSize( Vcb ), 01550 FALSE, 01551 SectorBuffer, 01552 Vcb->TargetDeviceObject ); 01553 01554 // 01555 // Verify the descriptor at the head of the sparing table. If it is not 01556 // valid, we just break out for a chance at the next table, if any. 01557 // 01558 01559 if (ByteOffset == 0) { 01560 01561 Header = (PSPARING_TABLE_HEADER) SectorBuffer; 01562 01563 if (!UdfVerifyDescriptor( IrpContext, 01564 &Header->Destag, 01565 0, 01566 SectorSize( Vcb ), 01567 Header->Destag.Lbn, 01568 TRUE )) { 01569 01570 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify destag!\n", 01571 SparingTable )); 01572 break; 01573 } 01574 01575 if (!UdfUdfIdentifierContained( &Header->RegID, 01576 &UdfSparingTableIdentifier, 01577 UDF_VERSION_150, 01578 UDF_VERSION_RECOGNIZED, 01579 OSCLASS_INVALID, 01580 OSIDENTIFIER_INVALID)) { 01581 01582 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table %u didn't verify regid!\n", 01583 SparingTable )); 01584 break; 01585 } 01586 01587 // 01588 // Calculate the total number bytes this map spans and check it against what 01589 // we were told the sparing table sizes are. 01590 // 01591 01592 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, Sparing table %u has %u entries\n", 01593 SparingTable, 01594 Header->TableEntries )); 01595 01596 TotalBytes = sizeof(SPARING_TABLE_HEADER) + Header->TableEntries * sizeof(SPARING_TABLE_ENTRY); 01597 01598 if (Map->TableSize < TotalBytes) { 01599 01600 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, sparing table #ents %u overflows allocation!\n", 01601 Header->TableEntries )); 01602 break; 01603 } 01604 01605 // 01606 // So far so good, advance past the header. 01607 // 01608 01609 ByteOffset = sizeof(SPARING_TABLE_HEADER); 01610 Entry = Add2Ptr( SectorBuffer, sizeof(SPARING_TABLE_HEADER), PSPARING_TABLE_ENTRY ); 01611 01612 } else { 01613 01614 // 01615 // Pick up in the new sector. 01616 // 01617 01618 Entry = (PSPARING_TABLE_ENTRY) SectorBuffer; 01619 } 01620 01621 RemainingBytes = Min( SectorSize( Vcb ), TotalBytes - ByteOffset ); 01622 } 01623 01624 // 01625 // Add the mapping. Since sparing tables are an Lbn->Psn mapping, 01626 // very odd, and I want to simplify things by putting the sparing 01627 // in right at IO dispatch, translate this to a Psn->Psn mapping. 01628 // 01629 01630 if (Entry->Original != UDF_SPARING_AVALIABLE && 01631 Entry->Original != UDF_SPARING_DEFECTIVE) { 01632 01633 Psn = Partition->Physical.Start + SectorsFromBlocks( Vcb, Entry->Original ); 01634 01635 DebugTrace(( 0, Dbg, "UdfLoadSparingTables, mapping from Psn %x (Lbn %x) -> Psn %x\n", 01636 Psn, 01637 Entry->Original, 01638 Entry->Mapped )); 01639 01640 FsRtlAddLargeMcbEntry( Pcb->SparingMcb, 01641 Psn, 01642 Entry->Mapped, 01643 UDF_SPARING_PACKET_LENGTH ); 01644 } 01645 01646 // 01647 // Advance to the next, and drop out if we've hit the end. 01648 // 01649 01650 ByteOffset += sizeof(SPARING_TABLE_ENTRY); 01651 RemainingBytes -= sizeof(SPARING_TABLE_ENTRY); 01652 Entry++; 01653 01654 } while ( ByteOffset < TotalBytes ); 01655 } 01656 01657 } finally { 01658 01659 DebugUnwind( UdfLoadSparingTables ); 01660 01661 UdfFreePool( &SectorBuffer ); 01662 } 01663 01664 DebugTrace(( -1, Dbg, "UdfLoadSparingTables -> STATUS_SUCCESS\n" )); 01665 01666 return STATUS_SUCCESS; 01667 } }

BOOLEAN UdfLookupAllocation IN PIRP_CONTEXT  IrpContext,
IN PFCB  Fcb,
IN LONGLONG  FileOffset,
OUT PLONGLONG  DiskOffset,
OUT PULONG  ByteCount
 

Definition at line 69 of file allocsup.c.

References ASSERT, ASSERT_FCB, ASSERT_IRP_CONTEXT, BytesFromSectors, Dbg, DebugTrace, FALSE, FCB_STATE_EMBEDDED_DATA, FCB_STATE_MCB_INITIALIZED, FCB_STATE_VMCB_MAPPING, FlagOn, FsRtlLookupLargeMcbEntry(), LlBytesFromSectors, LlSectorsFromBytes, NULL, PAGED_CODE, _VCB::Pcb, PFCB, SectorOffset, SectorsFromBytes, _PCB::SparingMcb, TRUE, UdfMethod2NextRunoutInSectors, UdfMethod2TransformByteOffset, UdfVmcbVbnToLbn(), VCB_STATE_METHOD_2_FIXUP, _VCB::VcbState, and _VCB::Vmcb.

Referenced by UdfPrepareBuffers().

00079 : 00080 00081 This routine looks through the mapping information for the file 00082 to find the logical diskoffset and number of bytes at that offset. 00083 00084 This routine assumes we are looking up a valid range in the file. If 00085 a mapping does not exist, 00086 00087 Arguments: 00088 00089 Fcb - Fcb representing this stream. 00090 00091 FileOffset - Lookup the allocation beginning at this point. 00092 00093 DiskOffset - Address to store the logical disk offset. 00094 00095 ByteCount - Address to store the number of contiguous bytes beginning 00096 at DiskOffset above. 00097 00098 Return Value: 00099 00100 BOOLEAN - whether the extent is unrecorded data 00101 00102 --*/ 00103 00104 { 00105 PVCB Vcb; 00106 00107 BOOLEAN Recorded = TRUE; 00108 00109 BOOLEAN Result; 00110 00111 LARGE_INTEGER LocalPsn; 00112 LARGE_INTEGER LocalSectorCount; 00113 00114 PAGED_CODE(); 00115 00116 // 00117 // Check inputs 00118 // 00119 00120 ASSERT_IRP_CONTEXT( IrpContext ); 00121 ASSERT_FCB( Fcb ); 00122 00123 // 00124 // We will never be looking up the allocations of embedded objects. 00125 // 00126 00127 ASSERT( !FlagOn( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA )); 00128 00129 Vcb = Fcb->Vcb; 00130 00131 LocalPsn.QuadPart = LocalSectorCount.QuadPart = 0; 00132 00133 // 00134 // Lookup the entry containing this file offset. 00135 // 00136 00137 if (FlagOn( Fcb->FcbState, FCB_STATE_VMCB_MAPPING )) { 00138 00139 // 00140 // Map this offset into the metadata stream. 00141 // 00142 00143 ASSERT( SectorOffset( Vcb, FileOffset ) == 0 ); 00144 00145 Result = UdfVmcbVbnToLbn( &Vcb->Vmcb, 00146 SectorsFromBytes( Vcb, FileOffset ), 00147 &LocalPsn.LowPart, 00148 &LocalSectorCount.LowPart ); 00149 00150 ASSERT( Result ); 00151 00152 } else { 00153 00154 // 00155 // Map this offset in a regular stream. 00156 // 00157 00158 ASSERT( FlagOn( Fcb->FcbState, FCB_STATE_MCB_INITIALIZED )); 00159 00160 Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb, 00161 LlSectorsFromBytes( Vcb, FileOffset ), 00162 &LocalPsn.QuadPart, 00163 &LocalSectorCount.QuadPart, 00164 NULL, 00165 NULL, 00166 NULL ); 00167 } 00168 00169 // 00170 // If within the Mcb then we use the data out of this entry and are nearly done. 00171 // 00172 00173 if (Result) { 00174 00175 if ( LocalPsn.QuadPart == -1 ) { 00176 00177 // 00178 // Regular files can have holey allocations which represent unrecorded extents. For 00179 // such extents which are sandwiched in between recorded extents of the file, the Mcb 00180 // package tells us that it found a valid mapping but that it doesn't correspond to 00181 // any extents on the media yet. In this case, simply fake the disk offset. The 00182 // returned sector count is accurate. 00183 // 00184 00185 *DiskOffset = 0; 00186 00187 Recorded = FALSE; 00188 00189 } else { 00190 00191 // 00192 // Now mimic the effects of physical sector sparing. This may shrink the size of the 00193 // returned run if sparing interrupted the extent on disc. 00194 // 00195 00196 ASSERT( LocalPsn.HighPart == 0 ); 00197 00198 if (Vcb->Pcb->SparingMcb) { 00199 00200 LONGLONG SparingPsn; 00201 LONGLONG SparingSectorCount; 00202 00203 if (FsRtlLookupLargeMcbEntry( Vcb->Pcb->SparingMcb, 00204 LocalPsn.LowPart, 00205 &SparingPsn, 00206 &SparingSectorCount, 00207 NULL, 00208 NULL, 00209 NULL )) { 00210 00211 // 00212 // Only emit noise if we will really change anything as a result 00213 // of the sparing table. 00214 // 00215 00216 if (SparingPsn != -1 || 00217 SparingSectorCount < LocalSectorCount.QuadPart) { 00218 00219 DebugTrace(( 0, Dbg, "UdfLookupAllocation, spared [%x, +%x) onto [%x, +%x)\n", 00220 LocalPsn.LowPart, 00221 LocalSectorCount.LowPart, 00222 (ULONG) SparingPsn, 00223 (ULONG) SparingSectorCount )); 00224 } 00225 00226 // 00227 // If we did not land in a hole, map the sector. 00228 // 00229 00230 if (SparingPsn != -1) { 00231 00232 LocalPsn.QuadPart = SparingPsn; 00233 } 00234 00235 // 00236 // The returned sector count now reduces the previous sector count. 00237 // If we landed in a hole, this indicates that the trailing edge of 00238 // the extent is spared, if not this indicates that the leading 00239 // edge is spared. 00240 // 00241 00242 if (SparingSectorCount < LocalSectorCount.QuadPart) { 00243 00244 LocalSectorCount.QuadPart = SparingSectorCount; 00245 } 00246 } 00247 } 00248 00249 *DiskOffset = LlBytesFromSectors( Vcb, LocalPsn.QuadPart ) + SectorOffset( Vcb, FileOffset ); 00250 00251 // 00252 // Now we can apply method 2 fixups, which will again interrupt the size of the extent. 00253 // 00254 00255 if (FlagOn( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) { 00256 00257 LARGE_INTEGER SectorsToRunout; 00258 00259 SectorsToRunout.QuadPart= UdfMethod2NextRunoutInSectors( Vcb, *DiskOffset ); 00260 00261 if (SectorsToRunout.QuadPart < LocalSectorCount.QuadPart) { 00262 00263 LocalSectorCount.QuadPart = SectorsToRunout.QuadPart; 00264 } 00265 00266 *DiskOffset = UdfMethod2TransformByteOffset( Vcb, *DiskOffset ); 00267 } 00268 } 00269 00270 } else { 00271 00272 // 00273 // We know that prior to this call the system has restricted IO to points within the 00274 // the file data. Since we failed to find a mapping this is an unrecorded extent at 00275 // the end of the file, so just conjure up a proper representation. 00276 // 00277 00278 ASSERT( FileOffset < Fcb->FileSize.QuadPart ); 00279 00280 *DiskOffset = 0; 00281 00282 LocalSectorCount.QuadPart = LlSectorsFromBytes( Vcb, Fcb->FileSize.QuadPart ) - 00283 LlSectorsFromBytes( Vcb, FileOffset ) + 00284 1; 00285 00286 Recorded = FALSE; 00287 } 00288 00289 // 00290 // Restrict to MAXULONG bytes of allocation 00291 // 00292 00293 if (LocalSectorCount.QuadPart > SectorsFromBytes( Vcb, MAXULONG )) { 00294 00295 *ByteCount = MAXULONG; 00296 00297 } else { 00298 00299 *ByteCount = BytesFromSectors( Vcb, LocalSectorCount.LowPart ); 00300 } 00301 00302 *ByteCount -= SectorOffset( Vcb, FileOffset ); 00303 00304 return Recorded; 00305 }

ULONG UdfLookupMetaVsnOfExtent IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb,
IN USHORT  Reference,
IN ULONG  Lbn,
IN ULONG  Len,
IN BOOLEAN  ExactEnd
 

Definition at line 1177 of file allocsup.c.

References ASSERT_IRP_CONTEXT, ASSERT_VCB, BlockOffset, BlocksFromBytes, BlocksFromSectors, CcSetFileSizes(), FALSE, LlBytesFromSectors, NULL, PCC_FILE_SIZES, SectorsFromBytes, TRUE, try_leave, UdfAddVmcbMapping(), UdfLockFcb, UdfLookupPsnOfExtent(), UdfRaiseStatus(), UdfRemoveVmcbMapping(), UdfUnlockFcb, and UdfVmcbLbnToVbn().

Referenced by UdfInitializeAllocations(), UdfMapMetadataView(), and UdfUpdateVcbPhase0().

01188 : 01189 01190 This routine maps the input logical block extent on a given partition to 01191 a starting virtual block in the metadata stream. If a mapping does not 01192 exist, one will be created and the metadata stream extended. 01193 01194 Arguments: 01195 01196 Vcb - Vcb of logical volume 01197 01198 Reference - Partition reference to use in the mapping 01199 01200 Lbn - Logical block number 01201 01202 Len - Length of extent in bytes 01203 01204 ExactEnd - Indicates the extension policy if these blocks are not mapped. 01205 01206 Return Value: 01207 01208 ULONG virtual sector number 01209 01210 Raised status if the Lbn extent is split across multiple Vbn extents. 01211 01212 --*/ 01213 01214 { 01215 ULONG Vsn; 01216 ULONG Psn; 01217 ULONG SectorCount; 01218 01219 BOOLEAN Result; 01220 01221 BOOLEAN UnwindExtension = FALSE; 01222 LONGLONG UnwindAllocationSize; 01223 01224 PFCB Fcb = NULL; 01225 01226 // 01227 // Check inputs 01228 // 01229 01230 ASSERT_IRP_CONTEXT( IrpContext ); 01231 ASSERT_VCB( Vcb ); 01232 01233 // 01234 // The extent must be an integral number of logical blocks in length. 01235 // 01236 01237 if (Len == 0 || BlockOffset( Vcb, Len )) { 01238 01239 UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); 01240 } 01241 01242 01243 // 01244 // Get the physical mapping of the extent. The Mcb package operates on ULONG/ULONG 01245 // keys and values so we must render our 48bit address into 32. We can do this since 01246 // this is a single surface implementation, and it is guaranteed that a surface cannot 01247 // contain more than MAXULONG physical sectors. 01248 // 01249 01250 Psn = UdfLookupPsnOfExtent( IrpContext, 01251 Vcb, 01252 Reference, 01253 Lbn, 01254 Len ); 01255 01256 // 01257 // Use try-finally for cleanup 01258 // 01259 01260 try { 01261 01262 // 01263 // We must safely establish a mapping and extend the metadata stream so that cached 01264 // reads can occur on this new extent. 01265 // 01266 01267 Fcb = Vcb->MetadataFcb; 01268 UdfLockFcb( IrpContext, Fcb ); 01269 01270 Result = UdfVmcbLbnToVbn( &Vcb->Vmcb, 01271 Psn, 01272 &Vsn, 01273 &SectorCount ); 01274 01275 if (Result) { 01276 01277 // 01278 // If the mapping covers the extent, we can give this back. 01279 // 01280 01281 if (BlocksFromSectors( Vcb, SectorCount ) >= BlocksFromBytes( Vcb, Len )) { 01282 01283 try_leave( NOTHING ); 01284 01285 } 01286 01287 // 01288 // It is a fatal error if the extent we are mapping is not wholly contained 01289 // by an extent of Vsns in the Vmcb. This will indicate that some structure 01290 // is trying to overlap another. 01291 // 01292 01293 UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); 01294 } 01295 01296 // 01297 // Add the new mapping. We know that it is being added to the end of the stream. 01298 // 01299 01300 UdfAddVmcbMapping( &Vcb->Vmcb, 01301 Psn, 01302 SectorsFromBytes( Vcb, Len ), 01303 ExactEnd, 01304 &Vsn, 01305 &SectorCount ); 01306 01307 UnwindAllocationSize = Fcb->AllocationSize.QuadPart; 01308 UnwindExtension = TRUE; 01309 01310 Fcb->AllocationSize.QuadPart = 01311 Fcb->FileSize.QuadPart = 01312 Fcb->ValidDataLength.QuadPart = LlBytesFromSectors( Vcb, Vsn + SectorCount); 01313 01314 CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize ); 01315 UnwindExtension = FALSE; 01316 01317 // 01318 // We do not need to purge the cache maps since the Vmcb will always be 01319 // page aligned, and thus any reads will have filled it with valid data. 01320 // 01321 01322 } finally { 01323 01324 if (UnwindExtension) { 01325 01326 ULONG FirstZappedVsn; 01327 01328 // 01329 // Strip off the additional mappings we made. 01330 // 01331 01332 Fcb->AllocationSize.QuadPart = 01333 Fcb->FileSize.QuadPart = 01334 Fcb->ValidDataLength.QuadPart = UnwindAllocationSize; 01335 01336 FirstZappedVsn = SectorsFromBytes( Vcb, UnwindAllocationSize ); 01337 01338 UdfRemoveVmcbMapping( &Vcb->Vmcb, 01339 FirstZappedVsn, 01340 Vsn + SectorCount - FirstZappedVsn ); 01341 01342 CcSetFileSizes( Fcb->FileObject, (PCC_FILE_SIZES) &Fcb->AllocationSize ); 01343 } 01344 01345 if (Fcb) { UdfUnlockFcb( IrpContext, Fcb ); } 01346 } 01347 01348 return Vsn; 01349 }

ULONG UdfLookupPsnOfExtent IN PIRP_CONTEXT  IrpContext,
IN PVCB  Vcb,
IN USHORT  Reference,
IN ULONG  Lbn,
IN ULONG  Len
 

Definition at line 1017 of file allocsup.c.

References ASSERT, ASSERT_IRP_CONTEXT, ASSERT_PCB, ASSERT_VCB, BlocksFromBytes, BlockSize, CcMapData(), Dbg, DebugTrace, DebugUnwind, FALSE, _tagPARTITION::Length, Offset, PAGED_CODE, _PCB::Partition, _PCB::Partitions, PBCB, Physical, SectorsFromBlocks, SectorsFromBytes, TRUE, UdfLookupPsnOfExtent(), UdfRaiseStatus(), UdfUnpinData, and Virtual.

Referenced by UdfFindFileSetDescriptor(), UdfInitializeAllocations(), UdfLookupMetaVsnOfExtent(), and UdfLookupPsnOfExtent().

01027 : 01028 01029 This routine maps the input logical block extent on a given partition to 01030 a starting physical sector. It doubles as a bounds checker - if the routine 01031 does not raise, the caller is guaranteed that the extent lies within the 01032 partition. 01033 01034 Arguments: 01035 01036 Vcb - Vcb of logical volume 01037 01038 Reference - Partition reference to use in the mapping 01039 01040 Lbn - Logical block number 01041 01042 Len - Length of extent in bytes 01043 01044 Return Value: 01045 01046 ULONG physical sector number 01047 01048 --*/ 01049 01050 { 01051 PPCB Pcb = Vcb->Pcb; 01052 ULONG Psn; 01053 01054 PBCB Bcb; 01055 LARGE_INTEGER Offset; 01056 PULONG MappedLbn; 01057 01058 PAGED_CODE(); 01059 01060 // 01061 // Check inputs 01062 // 01063 01064 ASSERT_IRP_CONTEXT( IrpContext ); 01065 ASSERT_VCB( Vcb ); 01066 ASSERT_PCB( Pcb ); 01067 01068 DebugTrace(( +1, Dbg, "UdfLookupPsnOfExtent, [%04x/%08x, +%08x)\n", Reference, Lbn, Len )); 01069 01070 if (Reference < Pcb->Partitions) { 01071 01072 while (TRUE) { 01073 01074 switch (Pcb->Partition[Reference].Type) { 01075 01076 case Physical: 01077 01078 // 01079 // Check that the input extent lies inside the partition. Calculate the 01080 // Lbn of the last block and see that it is interior. 01081 // 01082 01083 if (SectorsFromBlocks( Vcb, Lbn ) + SectorsFromBytes( Vcb, Len ) > 01084 Pcb->Partition[Reference].Physical.Length) { 01085 01086 goto NoGood; 01087 } 01088 01089 Psn = Pcb->Partition[Reference].Physical.Start + SectorsFromBlocks( Vcb, Lbn ); 01090 01091 DebugTrace(( -1, Dbg, "UdfLookupPsnOfExtent -> %08x\n", Psn )); 01092 return Psn; 01093 01094 case Virtual: 01095 01096 // 01097 // Bounds check. Per UDF 2.00 2.3.10 and implied in UDF 1.50, virtual 01098 // extent lengths cannot be greater than one block in size. 01099 // 01100 01101 if (Lbn + BlocksFromBytes( Vcb, Len ) > Pcb->Partition[Reference].Virtual.Length || 01102 Len > BlockSize( Vcb )) { 01103 01104 goto NoGood; 01105 } 01106 01107 try { 01108 01109 // 01110 // Calculate the location of the mapping element in the VAT 01111 // and retrieve. 01112 // 01113 01114 Offset.QuadPart = Lbn * sizeof(ULONG); 01115 01116 CcMapData( Vcb->VatFcb->FileObject, 01117 &Offset, 01118 sizeof(ULONG), 01119 TRUE, 01120 &Bcb, 01121 &MappedLbn ); 01122 01123 // 01124 // Now rewrite the inputs in terms of the virtual mapping. We 01125 // will reloop to perform the logical -> physical mapping. 01126 // 01127 01128 DebugTrace(( 0, Dbg, 01129 "UdfLookupPsnOfExtent, Mapping V %04x/%08x -> L %04x/%08x\n", 01130 Reference, 01131 Lbn, 01132 Pcb->Partition[Reference].Virtual.RelatedReference, 01133 *MappedLbn )); 01134 01135 Lbn = *MappedLbn; 01136 Reference = Pcb->Partition[Reference].Virtual.RelatedReference; 01137 01138 } finally { 01139 01140 DebugUnwind( UdfLookupPsnOfExtent ); 01141 01142 UdfUnpinData( IrpContext, &Bcb ); 01143 } 01144 01145 // 01146 // An Lbn of ~0 in the VAT is defined to indicate that the sector is unused, 01147 // so we should never see such a thing. 01148 // 01149 01150 if (Lbn == ~0) { 01151 01152 goto NoGood; 01153 } 01154 01155 break; 01156 01157 default: 01158 01159 ASSERT(FALSE); 01160 break; 01161 } 01162 } 01163 } 01164 01165 NoGood: 01166 01167 // 01168 // Some people have misinterpreted a partition number to equal a 01169 // partition reference, or perhaps this is just corrupt media. 01170 // 01171 01172 UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR ); 01173 }


Generated on Sat May 15 19:42:51 2004 for test by doxygen 1.3.7