1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
13 This file contains filesystem-specific routines
14 responsible for disk space management
20 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_ALLOC
22 static const int8 bit_count_tab
[] = {
23 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
24 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
25 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
26 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
27 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
28 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
29 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
30 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
32 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
33 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
34 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
35 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
36 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
37 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
38 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
39 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
43 This routine converts physical address to logical in specified partition
52 PUDFPartMap pm
= Vcb
->Partitions
;
53 #if defined (_X86_) && defined (_MSC_VER) && !defined(__clang__)
61 mov edx
,[ebx
]Vcb
.PartitionMaps
68 cmp
[ebx
]pm
.PartitionNum
,cx
71 sub eax
,[ebx
]pm
.PartitionRoot
73 mov ecx
,[ecx
]Vcb
.LB2B_Bits
77 add ebx
,size UDFPartMap
89 // validate return value
91 locAddr
.logicalBlockNum
= retval
;
92 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
93 UDFPartLbaToPhys(Vcb
, &locAddr
);
97 #else // NO X86 optimization , use generic C/C++
99 // walk through partition maps to find suitable one...
100 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++, pm
++) {
101 if(pm
->PartitionNum
== PartNum
)
102 // wow! return relative address
103 return (Addr
- pm
->PartitionRoot
) >> Vcb
->LB2B_Bits
;
107 } // end UDFPhysLbaToPart()
110 This routine returns physycal Lba for partition-relative addr
120 if(Addr
->partitionReferenceNum
>= Vcb
->PartitionMaps
) {
121 AdPrint(("UDFPartLbaToPhys: part %x, lbn %x (err)\n",
122 Addr
->partitionReferenceNum
, Addr
->logicalBlockNum
));
123 if(Vcb
->PartitionMaps
&&
124 (Vcb
->CompatFlags
& UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS
)) {
125 AdPrint(("UDFPartLbaToPhys: try to recover: part %x -> %x\n",
126 Addr
->partitionReferenceNum
, Vcb
->PartitionMaps
-1));
127 Addr
->partitionReferenceNum
= (USHORT
)(Vcb
->PartitionMaps
-1);
129 return LBA_OUT_OF_EXTENT
;
132 // walk through partition maps & transform relative address
134 for(i
=Addr
->partitionReferenceNum
; i
<Vcb
->PartitionMaps
; i
++) {
135 if(Vcb
->Partitions
[i
].PartitionNum
== Addr
->partitionReferenceNum
) {
136 a
= Vcb
->Partitions
[i
].PartitionRoot
+
137 (Addr
->logicalBlockNum
<< Vcb
->LB2B_Bits
);
138 if(a
> Vcb
->LastPossibleLBA
) {
139 AdPrint(("UDFPartLbaToPhys: root %x, lbn %x, lba %x (err1)\n",
140 Vcb
->Partitions
[i
].PartitionRoot
, Addr
->logicalBlockNum
, a
));
142 return LBA_OUT_OF_EXTENT
;
147 a
= Vcb
->Partitions
[i
-1].PartitionRoot
+
148 (Addr
->logicalBlockNum
<< Vcb
->LB2B_Bits
);
149 if(a
> Vcb
->LastPossibleLBA
) {
150 AdPrint(("UDFPartLbaToPhys: i %x, root %x, lbn %x, lba %x (err2)\n",
151 i
, Vcb
->Partitions
[i
-1].PartitionRoot
, Addr
->logicalBlockNum
, a
));
153 return LBA_OUT_OF_EXTENT
;
156 } // end UDFPartLbaToPhys()
160 This routine returns physycal Lba for partition-relative addr
161 No partition bounds check is performed.
162 This routine only checks if requested partition exists.
163 It is introduced for 'Adaptec DirectCD' compatibility,
164 because it uses negative values as extent terminator (against standard)
168 UDFPartLbaToPhysCompat(
174 if(Addr->partitionReferenceNum >= Vcb->PartitionMaps) return LBA_NOT_ALLOCATED;
175 // walk through partition maps & transform relative address
177 for(i=Addr->partitionReferenceNum; i<Vcb->PartitionMaps; i++) {
178 if(Vcb->Partitions[i].PartitionNum == Addr->partitionReferenceNum) {
179 a = Vcb->Partitions[i].PartitionRoot +
180 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
181 if(a > Vcb->LastPossibleLBA) {
187 a = Vcb->Partitions[i-1].PartitionRoot +
188 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
189 if(a > Vcb->LastPossibleLBA) {
193 } // end UDFPartLbaToPhysCompat()*/
197 This routine looks for the partition containing given physical sector
201 UDFGetPartNumByPhysLba(
206 uint32 i
=Vcb
->PartitionMaps
-1, root
;
207 PUDFPartMap pm
= &(Vcb
->Partitions
[i
]);
208 // walk through the partition maps to find suitable one
209 for(;i
!=0xffffffff;i
--,pm
--) {
210 if( ((root
= pm
->PartitionRoot
) <= Lba
) &&
211 ((root
+ pm
->PartitionLen
) > Lba
) ) return (uint16
)pm
->PartitionNum
;
213 return LBA_OUT_OF_EXTENT
; // Lba doesn't belong to any partition
214 } // end UDFGetPartNumByPhysLba()
217 Very simple routine. It walks through the Partition Maps & returns
218 the 1st Lba of the 1st suitable one
228 if(PartNum
== (uint32
)-1) return 0;
229 if(PartNum
== (uint32
)-2) return Vcb
->Partitions
[0].PartitionRoot
;
230 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++) {
231 if(Vcb
->Partitions
[i
].PartitionNum
== PartNum
) return Vcb
->Partitions
[i
].PartitionRoot
;
234 } // end UDFPartStart(
237 This routine does almost the same as previous.
238 The only difference is changing First Lba to Last one...
248 if(PartNum
== (uint32
)-1) return Vcb
->LastLBA
;
249 if(PartNum
== (uint32
)-2) PartNum
= Vcb
->PartitionMaps
-1;
250 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++) {
251 if(Vcb
->Partitions
[i
].PartitionNum
== PartNum
)
252 return (Vcb
->Partitions
[i
].PartitionRoot
+
253 Vcb
->Partitions
[i
].PartitionLen
);
255 return (Vcb
->Partitions
[i
-1].PartitionRoot
+
256 Vcb
->Partitions
[i
-1].PartitionLen
);
257 } // end UDFPartEnd()
260 Very simple routine. It walks through the Partition Maps & returns
261 the 1st Lba of the 1st suitable one
271 if(PartNum
== (uint32
)-2) return UDFPartEnd(Vcb
, -2) - UDFPartStart(Vcb
, -2);
278 jne short NOT_last_gpl
279 mov eax,[ebx]Vcb.LastLBA
284 mov ecx,[ebx]Vcb.PartitionMaps
288 mov edx,size UDFTrackMap
293 cmp [ebx]Vcb.PartitionMaps.PartitionNum,ax
295 add ebx,size UDFTrackMap
299 sub ebx,size UDFTrackMap
301 mov eax,[ebx]Vcb.PartitionMaps.PartitionLen
302 add eax,[ebx]Vcb.PartitionMaps.PartitionRoot
307 #else // NO X86 optimization , use generic C/C++*/
309 if(PartNum
== (uint32
)-1) return Vcb
->LastLBA
;
310 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++) {
311 if(Vcb
->Partitions
[i
].PartitionNum
== PartNum
)
312 return Vcb
->Partitions
[i
].PartitionLen
;
314 return (Vcb
->Partitions
[i
-1].PartitionRoot
+
315 Vcb
->Partitions
[i
-1].PartitionLen
);
317 } // end UDFPartLen()
320 This routine returns length of bit-chain starting from Offs bit in
321 array Bitmap. Bitmap scan is limited with Lim.
324 #if defined (_X86_) && defined (_MSC_VER)
332 uint32 Lim
// NOT included
345 xor edx
,edx
// init bit-counter
346 mov ebx
,[ebp
+0x08] // set base pointer in EBX (Bitmap)
347 mov esi
,[ebp
+0x0c] // set Offs in ESI
348 mov edi
,[ebp
+0x10] // set Lim in EDI
350 // check if Lim <= Offs
360 // set 1st bit number in CL
363 // make ESI uint32-index
366 // save last bit number in CH
370 // make EDI uint32-index of the last uint32
379 /* COUNT 1-BITS SECTION */
383 ja exit_count
// must never happen
428 /* COUNT 0-BITS SECTION */
432 ja exit_count
// must never happen
492 #else // NO X86 optimization , use generic C/C++
499 uint32 Lim
// NOT included
504 return 0;//(Offs == Lim);
507 BOOLEAN bit
= UDFGetBit(Bitmap
, Offs
);
510 uint8 j
=(uint8
)(Offs
&31);
511 uint8 lLim
=(uint8
)(Lim
&31);
515 ASSERT((bit
== 0) || (bit
== 1));
523 while( j
< ((i
<Lim
) ? 32 : lLim
) ) {
524 if( ((BOOLEAN
)(a
&1)) != bit
)
536 if((bit
&& (a
==0xffffffff)) ||
548 } // end UDFGetBitmapLen()
550 #ifndef UDF_READ_ONLY_BUILD
552 This routine scans disc free space Bitmap for minimal suitable extent.
553 It returns maximal available extent if no long enough extents found.
556 UDFFindMinSuitableExtent(
558 IN uint32 Length
, // in blocks
559 IN uint32 SearchStart
,
560 IN uint32 SearchLim
, // NOT included
561 OUT uint32
* MaxExtLen
,
571 BOOLEAN align
= FALSE
;
572 uint32 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
574 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
576 // we'll try to allocate packet-aligned block at first
577 if(!(Length
& (PS
-1)) && !Vcb
->CDR_Mode
&& (Length
>= PS
*2))
579 if(AllocFlags
& EXTENT_FLAG_ALLOC_SEQUENTIAL
)
581 if(Length
> (uint32
)(UDF_MAX_EXTENT_LENGTH
>> Vcb
->BlockSizeBits
))
582 Length
= (UDF_MAX_EXTENT_LENGTH
>> Vcb
->BlockSizeBits
);
583 // align Length according to _Logical_ block size & convert it to BCount
584 i
= (1<<Vcb
->LB2B_Bits
)-1;
585 Length
= (Length
+i
) & ~i
;
586 cur
= (uint32
*)(Vcb
->FSBM_Bitmap
);
593 ASSERT(i
<= SearchLim
);
595 i
= (i
+PS
-1) & ~(PS
-1);
596 ASSERT(i
<= SearchLim
);
600 len
= UDFGetBitmapLen(cur
, i
, SearchLim
);
601 if(UDFGetFreeBit(cur
, i
)) { // is the extent found free or used ?
604 // minimize extent length
605 if(!best_len
|| (best_len
> len
)) {
612 // remember max extent
618 // if this is CD-R mode, we should not think about fragmentation
619 // due to CD-R nature file will be fragmented in any case
620 if(Vcb
->CDR_Mode
) break;
624 // if we can't find suitable Packet-size aligned block,
625 // retry without any alignment requirements
626 if(!best_len
&& align
) {
631 // minimal suitable block
632 (*MaxExtLen
) = best_len
;
636 (*MaxExtLen
) = max_len
;
638 } // end UDFFindMinSuitableExtent()
639 #endif //UDF_READ_ONLY_BUILD
641 #ifdef UDF_CHECK_DISK_ALLOCATION
643 This routine checks space described by Mapping as Used/Freed (optionaly)
646 UDFCheckSpaceAllocation_(
650 #ifdef UDF_TRACK_ONDISK_ALLOCATION
652 IN uint32 BugCheckId
,
654 #endif //UDF_TRACK_ONDISK_ALLOCATION
658 uint32 lba
, j
, len
, BS
, BSh
;
659 BOOLEAN asUsed
= (asXXX
== AS_USED
);
664 BSh
= Vcb
->BlockSizeBits
;
666 UDFAcquireResourceShared(&(Vcb
->BitMapResource1
),TRUE
);
667 // walk through all frags in data area specified
668 #ifdef UDF_TRACK_ONDISK_ALLOCATION
669 AdPrint(("ChkAlloc:Map:%x:File:%x:Line:%d\n",
674 #endif //UDF_TRACK_ONDISK_ALLOCATION
675 while(Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) {
677 #ifdef UDF_TRACK_ONDISK_ALLOCATION
678 AdPrint(("ChkAlloc:%x:%s:%x:@:%x:(%x):File:%x:Line:%d\n",
681 (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
,
683 (Map
[i
].extLength
>> 30),
687 #endif //UDF_TRACK_ONDISK_ALLOCATION
689 UDFCheckUsedBitOwner(Vcb
, (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
, FE_lba
);
691 UDFCheckFreeBitOwner(Vcb
, (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
694 if((Map
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
695 // skip unallocated frags
696 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
697 ASSERT(!Map
[i
].extLocation
);
701 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
702 ASSERT(Map
[i
].extLocation
);
705 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
706 ASSERT(!(Map
[i
].extLength
& (BS
-1)));
707 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
708 len
= ((Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)+BS
-1) >> BSh
;
709 lba
= Map
[i
].extLocation
;
710 if((lba
+len
) > Vcb
->LastPossibleLBA
) {
711 // skip blocks beyond media boundary
712 if(lba
> Vcb
->LastPossibleLBA
) {
717 len
= Vcb
->LastPossibleLBA
- lba
;
720 // mark frag as XXX (see asUsed parameter)
725 if(lba
+j
> Vcb
->LastPossibleLBA
) {
727 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba
+j
));
730 if(!UDFGetUsedBit(Vcb
->FSBM_Bitmap
, lba
+j
)) {
732 AdPrint(("USED Mapping covers FREE block(s) @%x\n",lba
+j
));
741 if(lba
+j
> Vcb
->LastPossibleLBA
) {
743 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba
+j
));
746 if(!UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
+j
)) {
748 AdPrint(("FREE Mapping covers USED block(s) @%x\n",lba
+j
));
756 UDFReleaseResource(&(Vcb
->BitMapResource1
));
757 } // end UDFCheckSpaceAllocation_()
758 #endif //UDF_CHECK_DISK_ALLOCATION
761 UDFMarkBadSpaceAsUsed(
768 #define BIT_C (sizeof(Vcb->BSBM_Bitmap[0])*8)
769 len
= (lba
+len
+BIT_C
-1)/BIT_C
;
770 if(Vcb
->BSBM_Bitmap
) {
771 for(j
=lba
/BIT_C
; j
<len
; j
++) {
772 Vcb
->FSBM_Bitmap
[j
] &= ~Vcb
->BSBM_Bitmap
[j
];
776 } // UDFMarkBadSpaceAsUsed()
779 This routine marks space described by Mapping as Used/Freed (optionaly)
782 UDFMarkSpaceAsXXXNoProtect_(
786 #ifdef UDF_TRACK_ONDISK_ALLOCATION
788 IN uint32 BugCheckId
,
790 #endif //UDF_TRACK_ONDISK_ALLOCATION
794 uint32 lba
, j
, len
, BS
, BSh
;
796 BOOLEAN asUsed
= (asXXX
== AS_USED
|| (asXXX
& AS_BAD
));
797 #ifdef UDF_TRACK_ONDISK_ALLOCATION
798 BOOLEAN bit_before
, bit_after
;
799 #endif //UDF_TRACK_ONDISK_ALLOCATION
801 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
806 BSh
= Vcb
->BlockSizeBits
;
807 Vcb
->BitmapModified
= TRUE
;
809 // walk through all frags in data area specified
810 while(Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) {
811 if((Map
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
812 // skip unallocated frags
816 ASSERT(Map
[i
].extLocation
);
818 #ifdef UDF_TRACK_ONDISK_ALLOCATION
819 AdPrint(("Alloc:%x:%s:%x:@:%x:File:%x:Line:%d\n",
821 asUsed
? ((asXXX
& AS_BAD
) ? "B" : "U") : "F",
822 (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
,
827 #endif //UDF_TRACK_ONDISK_ALLOCATION
830 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
831 ASSERT(!(Map
[i
].extLength
& (BS
-1)));
832 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
833 // len = ((Map[i].extLength & UDF_EXTENT_LENGTH_MASK)+BS-1) >> BSh;
835 // len = (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh;
837 len
= ((Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)+BS
-1) >> BSh
;
838 lba
= Map
[i
].extLocation
;
839 if((lba
+len
) > Vcb
->LastPossibleLBA
) {
840 // skip blocks beyond media boundary
841 if(lba
> Vcb
->LastPossibleLBA
) {
846 len
= Vcb
->LastPossibleLBA
- lba
;
849 #ifdef UDF_TRACK_ONDISK_ALLOCATION
851 bit_before
= UDFGetBit(Vcb
->FSBM_Bitmap
, lba
-1);
852 bit_after
= UDFGetBit(Vcb
->FSBM_Bitmap
, lba
+len
);
853 #endif //UDF_TRACK_ONDISK_ALLOCATION
855 // mark frag as XXX (see asUsed parameter)
857 /* for(j=0;j<len;j++) {
858 UDFSetUsedBit(Vcb->FSBM_Bitmap, lba+j);
861 UDFSetUsedBits(Vcb
->FSBM_Bitmap
, lba
, len
);
862 #ifdef UDF_TRACK_ONDISK_ALLOCATION
864 ASSERT(UDFGetUsedBit(Vcb
->FSBM_Bitmap
, lba
+j
));
866 #endif //UDF_TRACK_ONDISK_ALLOCATION
869 // mark logical blocks in VAT as used
871 root
= UDFPartStart(Vcb
, UDFGetPartNumByPhysLba(Vcb
, lba
));
872 if((Vcb
->Vat
[lba
-root
+j
] == UDF_VAT_FREE_ENTRY
) &&
873 (lba
> Vcb
->LastLBA
)) {
874 Vcb
->Vat
[lba
-root
+j
] = 0x7fffffff;
879 /* for(j=0;j<len;j++) {
880 UDFSetFreeBit(Vcb->FSBM_Bitmap, lba+j);
883 UDFSetFreeBits(Vcb
->FSBM_Bitmap
, lba
, len
);
884 #ifdef UDF_TRACK_ONDISK_ALLOCATION
886 ASSERT(UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
+j
));
888 #endif //UDF_TRACK_ONDISK_ALLOCATION
890 UDFSetBits(Vcb
->BSBM_Bitmap
, lba
, len
);
892 UDFMarkBadSpaceAsUsed(Vcb
, lba
, len
);
894 if(asXXX
& AS_DISCARDED
) {
895 UDFUnmapRange(Vcb
, lba
, len
);
896 WCacheDiscardBlocks__(&(Vcb
->FastCache
), Vcb
, lba
, len
);
897 UDFSetZeroBits(Vcb
->ZSBM_Bitmap
, lba
, len
);
900 // mark logical blocks in VAT as free
901 // this operation can decrease resulting VAT size
903 root
= UDFPartStart(Vcb
, UDFGetPartNumByPhysLba(Vcb
, lba
));
904 Vcb
->Vat
[lba
-root
+j
] = UDF_VAT_FREE_ENTRY
;
907 // mark discarded extent as Not-Alloc-Not-Rec to
908 // prevent writes there
909 Map
[i
].extLength
= (len
<< BSh
) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
910 Map
[i
].extLocation
= 0;
913 #ifdef UDF_TRACK_ONDISK_ALLOCATION
915 ASSERT(bit_before
== UDFGetBit(Vcb
->FSBM_Bitmap
, lba
-1));
916 ASSERT(bit_after
== UDFGetBit(Vcb
->FSBM_Bitmap
, lba
+len
));
917 #endif //UDF_TRACK_ONDISK_ALLOCATION
921 } // end UDFMarkSpaceAsXXXNoProtect_()
924 This routine marks space described by Mapping as Used/Freed (optionaly)
925 It protects data with sync Resource
932 #ifdef UDF_TRACK_ONDISK_ALLOCATION
934 IN uint32 BugCheckId
,
936 #endif //UDF_TRACK_ONDISK_ALLOCATION
940 if(!Map
[0].extLength
) {
942 ASSERT(!Map
[0].extLocation
);
947 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
948 #ifdef UDF_TRACK_ONDISK_ALLOCATION
949 UDFMarkSpaceAsXXXNoProtect_(Vcb
, Map
, asXXX
, FE_lba
, BugCheckId
, Line
);
950 #else //UDF_TRACK_ONDISK_ALLOCATION
951 UDFMarkSpaceAsXXXNoProtect_(Vcb
, Map
, asXXX
);
952 #endif //UDF_TRACK_ONDISK_ALLOCATION
953 UDFReleaseResource(&(Vcb
->BitMapResource1
));
955 } // end UDFMarkSpaceAsXXX_()
957 #ifndef UDF_READ_ONLY_BUILD
959 This routine builds mapping for Length bytes in FreeSpace
960 It should be used when IN_ICB method is unavailable.
966 IN uint32 SearchStart
,
967 IN uint32 SearchLim
, // NOT included
968 OUT PEXTENT_INFO ExtInfo
,
970 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
973 #endif //UDF_TRACK_ALLOC_FREE_EXTENT
977 PEXTENT_MAP Map
= NULL
;
978 uint32 len
, LBS
, BSh
, blen
;
980 LBS
= Vcb
->LBlockSize
;
981 BSh
= Vcb
->BlockSizeBits
;
982 blen
= (uint32
)(((Length
+LBS
-1) & ~((int64
)LBS
-1)) >> BSh
);
983 ExtInfo
->Mapping
= NULL
;
986 ASSERT(blen
<= (uint32
)(UDF_MAX_EXTENT_LENGTH
>> BSh
));
988 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
990 if(blen
> (SearchLim
- SearchStart
)) {
991 goto no_free_space_err
;
993 // walk through the free space bitmap & find a single extent or a set of
994 // frags giving in sum the Length specified
996 Ext
.extLocation
= UDFFindMinSuitableExtent(Vcb
, blen
, SearchStart
,
997 SearchLim
, &len
, AllocFlags
);
999 // ASSERT(len <= (uint32)(UDF_MAX_EXTENT_LENGTH >> BSh));
1002 Ext
.extLength
= blen
<<BSh
;
1005 // we need still some frags to complete request &
1006 // probably we have the opportunity to do it
1007 Ext
.extLength
= len
<<BSh
;
1011 // no more free space. abort
1012 if(ExtInfo
->Mapping
) {
1013 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // free
1014 MyFreePool__(ExtInfo
->Mapping
);
1015 ExtInfo
->Mapping
= NULL
;
1017 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1018 ExtInfo
->Length
= 0;//UDFGetExtentLength(ExtInfo->Mapping);
1019 AdPrint((" DISK_FULL\n"));
1020 return STATUS_DISK_FULL
;
1022 // append the frag found to mapping
1023 ASSERT(!(Ext
.extLength
>> 30));
1024 ASSERT(Ext
.extLocation
);
1026 // mark newly allocated blocks as zero-filled
1027 UDFSetZeroBits(Vcb
->ZSBM_Bitmap
, Ext
.extLocation
, (Ext
.extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
1029 if(AllocFlags
& EXTENT_FLAG_VERIFY
) {
1030 if(!UDFCheckArea(Vcb
, Ext
.extLocation
, Ext
.extLength
>> BSh
)) {
1031 AdPrint(("newly allocated extent contains BB\n"));
1032 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // free
1033 UDFMarkBadSpaceAsUsed(Vcb
, Ext
.extLocation
, Ext
.extLength
>> BSh
); // bad -> bad+used
1035 blen
+= Ext
.extLength
>>BSh
;
1040 Ext
.extLength
|= EXTENT_NOT_RECORDED_ALLOCATED
<< 30;
1041 if(!(ExtInfo
->Mapping
)) {
1043 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
1044 ExtInfo
->Mapping
= UDFExtentToMapping_(&Ext
, src
, line
);
1045 #else // UDF_TRACK_ALLOC_FREE_EXTENT
1046 ExtInfo
->Mapping
= UDFExtentToMapping(&Ext
);
1047 #endif // UDF_TRACK_ALLOC_FREE_EXTENT
1048 if(!ExtInfo
->Mapping
) {
1050 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1051 ExtInfo
->Length
= 0;
1052 return STATUS_INSUFFICIENT_RESOURCES
;
1054 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // used
1057 Map
= UDFExtentToMapping(&Ext
);
1060 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1061 ExtInfo
->Length
= UDFGetExtentLength(ExtInfo
->Mapping
);
1062 return STATUS_INSUFFICIENT_RESOURCES
;
1064 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, Map
, AS_USED
); // used
1065 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, Map
);
1068 if(!ExtInfo
->Mapping
) {
1070 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1071 ExtInfo
->Length
= 0;
1072 return STATUS_INSUFFICIENT_RESOURCES
;
1075 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1076 ExtInfo
->Length
= Length
;
1077 return STATUS_SUCCESS
;
1078 } // end UDFAllocFreeExtent_()
1079 #endif //UDF_READ_ONLY_BUILD
1086 UDFGetPartFreeSpace(
1091 uint32 lim
/*, len=1*/;
1094 PUCHAR cur
= (PUCHAR
)(Vcb
->FSBM_Bitmap
);
1096 lim
= (UDFPartEnd(Vcb
,partNum
)+7)/8;
1097 for(j
=(UDFPartStart(Vcb
,partNum
)+7)/8; j
<lim
/* && len*/; j
++) {
1098 s
+=bit_count_tab
[cur
[j
]];
1101 } // end UDFGetPartFreeSpace()
1111 // uint32* cur = (uint32*)(Vcb->FSBM_Bitmap);
1113 if(!Vcb
->CDR_Mode
&&
1114 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
)) {
1115 for(i
=0;i
<Vcb
->PartitionMaps
;i
++) {
1116 /* lim = UDFPartEnd(Vcb,i);
1117 for(j=UDFPartStart(Vcb,i); j<lim && len; ) {
1118 len = UDFGetBitmapLen(cur, j, lim);
1119 if(UDFGetFreeBit(cur, j)) // is the extent found free or used ?
1123 s
+= UDFGetPartFreeSpace(Vcb
, i
);
1126 ASSERT(Vcb
->LastPossibleLBA
>= max(Vcb
->NWA
, Vcb
->LastLBA
));
1127 s
= Vcb
->LastPossibleLBA
- max(Vcb
->NWA
, Vcb
->LastLBA
);
1128 //if(s & ((int64)1 << 64)) s=0;
1130 return s
>> Vcb
->LB2B_Bits
;
1131 } // end UDFGetFreeSpace()
1145 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
1146 s
= Vcb
->LastPossibleLBA
;
1147 } else if(!Vcb
->CDR_Mode
) {
1148 for(i
=0;i
<Vcb
->PartitionMaps
;i
++) {
1149 s
+=Vcb
->Partitions
[i
].PartitionLen
;
1152 if(s
& ((int64
)1 << 63)) s
=0; /* FIXME ReactOS this shift value was 64, which is undefiened behavior. */
1153 s
= Vcb
->LastPossibleLBA
- Vcb
->Partitions
[0].PartitionRoot
;
1155 return s
>> Vcb
->LB2B_Bits
;
1156 } // end UDFGetTotalSpace()
1160 returns Allocated and Zero-filled flags for given block
1161 any data in 'unallocated' blocks may be changed during flush process
1164 UDFIsBlockAllocated(
1172 if(!(((PVCB
)_Vcb
)->VCBFlags
& UDF_VCB_ASSUME_ALL_USED
)) {
1174 if((bm
= (uint32
*)(((PVCB
)_Vcb
)->FSBM_Bitmap
)))
1175 ret_val
= (UDFGetUsedBit(bm
, Lba
) ? WCACHE_BLOCK_USED
: 0);
1176 // check zero-filled
1177 if((bm
= (uint32
*)(((PVCB
)_Vcb
)->ZSBM_Bitmap
)))
1178 ret_val
|= (UDFGetZeroBit(bm
, Lba
) ? WCACHE_BLOCK_ZERO
: 0);
1180 ret_val
= WCACHE_BLOCK_USED
;
1184 // WCache works with LOGICAL addresses, not PHYSICAL, BB check must be performed UNDER cache
1186 if(bm = (uint32*)(((PVCB)_Vcb)->BSBM_Bitmap)) {
1187 ret_val |= (UDFGetBadBit(bm, Lba) ? WCACHE_BLOCK_BAD : 0);
1188 if(ret_val & WCACHE_BLOCK_BAD) {
1189 UDFPrint(("Marked BB @ %#x\n", Lba));
1194 } // end UDFIsBlockAllocated()
1199 #pragma warning(disable:4035) // re-enable below
1208 IN uint32
* arr
, // ECX
1209 IN uint32 bit
// EDX
1213 // ASSERT(bit < 300000);
1222 add eax
,ecx
// eax+arr
1234 return ((BOOLEAN
)(((((uint32
*)(arr
))[(bit
)>>5]) >> ((bit
)&31)) &1));
1236 } // end UDFGetBit__()
1244 IN uint32
* arr
, // ECX
1245 IN uint32 bit
// EDX
1249 // ASSERT(bit < 300000);
1259 add eax
,ecx
// eax+arr
1272 (((uint32
*)(arr
))[(bit
)>>5]) |= (((uint32
)1) << ((bit
)&31));
1274 } // end UDFSetBit__()
1283 #if defined(_MSC_VER) && !defined(__clang__)
1306 jnz
short sb_loop_cont
1309 jb
short sb_loop_cont
1311 mov
[dword ptr esi
+eax
],0xffffffff
1327 jnz
short sb_loop_cont
1341 UDFSetBit(arr
, bit
+j
);
1344 } // end UDFSetBits__()
1352 IN uint32
* arr
, // ECX
1353 IN uint32 bit
// EDX
1357 // ASSERT(bit < 300000);
1367 add eax
,ecx
// eax+arr
1380 (((uint32
*)(arr
))[(bit
)>>5]) &= (~(((uint32
)1) << ((bit
)&31)));
1382 } // end UDFClrBit__()
1391 #if defined(_MSC_VER) && !defined(__clang__)
1414 jnz
short cp_loop_cont
1417 jb
short cp_loop_cont
1419 mov
[dword ptr esi
+eax
],0x00000000
1435 jnz
short cp_loop_cont
1449 UDFClrBit(arr
, bit
+j
);
1452 } // end UDFClrBits__()
1455 #pragma warning(default:4035)