test: allocsup.c File Reference

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 }