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
;
62 mov edx
,[ebx
]Vcb
.PartitionMaps
69 cmp
[ebx
]pm
.PartitionNum
,cx
72 sub eax
,[ebx
]pm
.PartitionRoot
74 mov ecx
,[ecx
]Vcb
.LB2B_Bits
78 add ebx
,size UDFPartMap
90 // validate return value
92 locAddr
.logicalBlockNum
= retval
;
93 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
94 UDFPartLbaToPhys(Vcb
, &locAddr
);
98 #else // NO X86 optimization , use generic C/C++
100 // walk through partition maps to find suitable one...
101 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++, pm
++) {
102 if(pm
->PartitionNum
== PartNum
)
103 // wow! return relative address
104 return (Addr
- pm
->PartitionRoot
) >> Vcb
->LB2B_Bits
;
108 } // end UDFPhysLbaToPart()
111 This routine returns physycal Lba for partition-relative addr
121 if(Addr
->partitionReferenceNum
>= Vcb
->PartitionMaps
) {
122 AdPrint(("UDFPartLbaToPhys: part %x, lbn %x (err)\n",
123 Addr
->partitionReferenceNum
, Addr
->logicalBlockNum
));
124 if(Vcb
->PartitionMaps
&&
125 (Vcb
->CompatFlags
& UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS
)) {
126 AdPrint(("UDFPartLbaToPhys: try to recover: part %x -> %x\n",
127 Addr
->partitionReferenceNum
, Vcb
->PartitionMaps
-1));
128 Addr
->partitionReferenceNum
= (USHORT
)(Vcb
->PartitionMaps
-1);
130 return LBA_OUT_OF_EXTENT
;
133 // walk through partition maps & transform relative address
135 for(i
=Addr
->partitionReferenceNum
; i
<Vcb
->PartitionMaps
; i
++) {
136 if(Vcb
->Partitions
[i
].PartitionNum
== Addr
->partitionReferenceNum
) {
137 a
= Vcb
->Partitions
[i
].PartitionRoot
+
138 (Addr
->logicalBlockNum
<< Vcb
->LB2B_Bits
);
139 if(a
> Vcb
->LastPossibleLBA
) {
140 AdPrint(("UDFPartLbaToPhys: root %x, lbn %x, lba %x (err1)\n",
141 Vcb
->Partitions
[i
].PartitionRoot
, Addr
->logicalBlockNum
, a
));
143 return LBA_OUT_OF_EXTENT
;
148 a
= Vcb
->Partitions
[i
-1].PartitionRoot
+
149 (Addr
->logicalBlockNum
<< Vcb
->LB2B_Bits
);
150 if(a
> Vcb
->LastPossibleLBA
) {
151 AdPrint(("UDFPartLbaToPhys: i %x, root %x, lbn %x, lba %x (err2)\n",
152 i
, Vcb
->Partitions
[i
-1].PartitionRoot
, Addr
->logicalBlockNum
, a
));
154 return LBA_OUT_OF_EXTENT
;
157 } // end UDFPartLbaToPhys()
161 This routine returns physycal Lba for partition-relative addr
162 No partition bounds check is performed.
163 This routine only checks if requested partition exists.
164 It is introduced for 'Adaptec DirectCD' compatibility,
165 because it uses negative values as extent terminator (against standard)
169 UDFPartLbaToPhysCompat(
175 if(Addr->partitionReferenceNum >= Vcb->PartitionMaps) return LBA_NOT_ALLOCATED;
176 // walk through partition maps & transform relative address
178 for(i=Addr->partitionReferenceNum; i<Vcb->PartitionMaps; i++) {
179 if(Vcb->Partitions[i].PartitionNum == Addr->partitionReferenceNum) {
180 a = Vcb->Partitions[i].PartitionRoot +
181 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
182 if(a > Vcb->LastPossibleLBA) {
188 a = Vcb->Partitions[i-1].PartitionRoot +
189 (Addr->logicalBlockNum << Vcb->LB2B_Bits);
190 if(a > Vcb->LastPossibleLBA) {
194 } // end UDFPartLbaToPhysCompat()*/
198 This routine looks for the partition containing given physical sector
202 UDFGetPartNumByPhysLba(
207 uint32 i
=Vcb
->PartitionMaps
-1, root
;
208 PUDFPartMap pm
= &(Vcb
->Partitions
[i
]);
209 // walk through the partition maps to find suitable one
210 for(;i
!=0xffffffff;i
--,pm
--) {
211 if( ((root
= pm
->PartitionRoot
) <= Lba
) &&
212 ((root
+ pm
->PartitionLen
) > Lba
) ) return (uint16
)pm
->PartitionNum
;
214 return LBA_OUT_OF_EXTENT
; // Lba doesn't belong to any partition
215 } // end UDFGetPartNumByPhysLba()
218 Very simple routine. It walks through the Partition Maps & returns
219 the 1st Lba of the 1st suitable one
229 if(PartNum
== (uint32
)-1) return 0;
230 if(PartNum
== (uint32
)-2) return Vcb
->Partitions
[0].PartitionRoot
;
231 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++) {
232 if(Vcb
->Partitions
[i
].PartitionNum
== PartNum
) return Vcb
->Partitions
[i
].PartitionRoot
;
235 } // end UDFPartStart(
238 This routine does almost the same as previous.
239 The only difference is changing First Lba to Last one...
249 if(PartNum
== (uint32
)-1) return Vcb
->LastLBA
;
250 if(PartNum
== (uint32
)-2) PartNum
= Vcb
->PartitionMaps
-1;
251 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++) {
252 if(Vcb
->Partitions
[i
].PartitionNum
== PartNum
)
253 return (Vcb
->Partitions
[i
].PartitionRoot
+
254 Vcb
->Partitions
[i
].PartitionLen
);
256 return (Vcb
->Partitions
[i
-1].PartitionRoot
+
257 Vcb
->Partitions
[i
-1].PartitionLen
);
258 } // end UDFPartEnd()
261 Very simple routine. It walks through the Partition Maps & returns
262 the 1st Lba of the 1st suitable one
272 if(PartNum
== (uint32
)-2) return UDFPartEnd(Vcb
, -2) - UDFPartStart(Vcb
, -2);
279 jne short NOT_last_gpl
280 mov eax,[ebx]Vcb.LastLBA
285 mov ecx,[ebx]Vcb.PartitionMaps
289 mov edx,size UDFTrackMap
294 cmp [ebx]Vcb.PartitionMaps.PartitionNum,ax
296 add ebx,size UDFTrackMap
300 sub ebx,size UDFTrackMap
302 mov eax,[ebx]Vcb.PartitionMaps.PartitionLen
303 add eax,[ebx]Vcb.PartitionMaps.PartitionRoot
308 #else // NO X86 optimization , use generic C/C++*/
310 if(PartNum
== (uint32
)-1) return Vcb
->LastLBA
;
311 for(i
=PartNum
; i
<Vcb
->PartitionMaps
; i
++) {
312 if(Vcb
->Partitions
[i
].PartitionNum
== PartNum
)
313 return Vcb
->Partitions
[i
].PartitionLen
;
315 return (Vcb
->Partitions
[i
-1].PartitionRoot
+
316 Vcb
->Partitions
[i
-1].PartitionLen
);
318 } // end UDFPartLen()
321 This routine returns length of bit-chain starting from Offs bit in
322 array Bitmap. Bitmap scan is limited with Lim.
334 uint32 Lim
// NOT included
347 xor edx
,edx
// init bit-counter
348 mov ebx
,[ebp
+0x08] // set base pointer in EBX (Bitmap)
349 mov esi
,[ebp
+0x0c] // set Offs in ESI
350 mov edi
,[ebp
+0x10] // set Lim in EDI
352 // check if Lim <= Offs
362 // set 1st bit number in CL
365 // make ESI uint32-index
368 // save last bit number in CH
372 // make EDI uint32-index of the last uint32
381 /* COUNT 1-BITS SECTION */
385 ja exit_count
// must never happen
430 /* COUNT 0-BITS SECTION */
434 ja exit_count
// must never happen
494 #else // NO X86 optimization , use generic C/C++
501 uint32 Lim
// NOT included
506 return 0;//(Offs == Lim);
509 BOOLEAN bit
= UDFGetBit(Bitmap
, Offs
);
512 uint8 j
=(uint8
)(Offs
&31);
513 uint8 lLim
=(uint8
)(Lim
&31);
517 ASSERT((bit
== 0) || (bit
== 1));
525 while( j
< ((i
<Lim
) ? 32 : lLim
) ) {
526 if( ((BOOLEAN
)(a
&1)) != bit
)
538 if((bit
&& (a
==0xffffffff)) ||
550 } // end UDFGetBitmapLen()
552 #ifndef UDF_READ_ONLY_BUILD
554 This routine scans disc free space Bitmap for minimal suitable extent.
555 It returns maximal available extent if no long enough extents found.
558 UDFFindMinSuitableExtent(
560 IN uint32 Length
, // in blocks
561 IN uint32 SearchStart
,
562 IN uint32 SearchLim
, // NOT included
563 OUT uint32
* MaxExtLen
,
573 BOOLEAN align
= FALSE
;
574 uint32 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
576 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
578 // we'll try to allocate packet-aligned block at first
579 if(!(Length
& (PS
-1)) && !Vcb
->CDR_Mode
&& (Length
>= PS
*2))
581 if(AllocFlags
& EXTENT_FLAG_ALLOC_SEQUENTIAL
)
583 if(Length
> (uint32
)(UDF_MAX_EXTENT_LENGTH
>> Vcb
->BlockSizeBits
))
584 Length
= (UDF_MAX_EXTENT_LENGTH
>> Vcb
->BlockSizeBits
);
585 // align Length according to _Logical_ block size & convert it to BCount
586 i
= (1<<Vcb
->LB2B_Bits
)-1;
587 Length
= (Length
+i
) & ~i
;
588 cur
= (uint32
*)(Vcb
->FSBM_Bitmap
);
595 ASSERT(i
<= SearchLim
);
597 i
= (i
+PS
-1) & ~(PS
-1);
598 ASSERT(i
<= SearchLim
);
602 len
= UDFGetBitmapLen(cur
, i
, SearchLim
);
603 if(UDFGetFreeBit(cur
, i
)) { // is the extent found free or used ?
606 // minimize extent length
607 if(!best_len
|| (best_len
> len
)) {
614 // remember max extent
620 // if this is CD-R mode, we should not think about fragmentation
621 // due to CD-R nature file will be fragmented in any case
622 if(Vcb
->CDR_Mode
) break;
626 // if we can't find suitable Packet-size aligned block,
627 // retry without any alignment requirements
628 if(!best_len
&& align
) {
633 // minimal suitable block
634 (*MaxExtLen
) = best_len
;
638 (*MaxExtLen
) = max_len
;
640 } // end UDFFindMinSuitableExtent()
641 #endif //UDF_READ_ONLY_BUILD
643 #ifdef UDF_CHECK_DISK_ALLOCATION
645 This routine checks space described by Mapping as Used/Freed (optionaly)
648 UDFCheckSpaceAllocation_(
652 #ifdef UDF_TRACK_ONDISK_ALLOCATION
654 IN uint32 BugCheckId
,
656 #endif //UDF_TRACK_ONDISK_ALLOCATION
660 uint32 lba
, j
, len
, BS
, BSh
;
661 BOOLEAN asUsed
= (asXXX
== AS_USED
);
666 BSh
= Vcb
->BlockSizeBits
;
668 UDFAcquireResourceShared(&(Vcb
->BitMapResource1
),TRUE
);
669 // walk through all frags in data area specified
670 #ifdef UDF_TRACK_ONDISK_ALLOCATION
671 AdPrint(("ChkAlloc:Map:%x:File:%x:Line:%d\n",
676 #endif //UDF_TRACK_ONDISK_ALLOCATION
677 while(Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) {
679 #ifdef UDF_TRACK_ONDISK_ALLOCATION
680 AdPrint(("ChkAlloc:%x:%s:%x:@:%x:(%x):File:%x:Line:%d\n",
683 (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
,
685 (Map
[i
].extLength
>> 30),
689 #endif //UDF_TRACK_ONDISK_ALLOCATION
691 UDFCheckUsedBitOwner(Vcb
, (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
, FE_lba
);
693 UDFCheckFreeBitOwner(Vcb
, (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
696 if((Map
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
697 // skip unallocated frags
698 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
699 ASSERT(!Map
[i
].extLocation
);
703 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
704 ASSERT(Map
[i
].extLocation
);
707 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
708 ASSERT(!(Map
[i
].extLength
& (BS
-1)));
709 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
710 len
= ((Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)+BS
-1) >> BSh
;
711 lba
= Map
[i
].extLocation
;
712 if((lba
+len
) > Vcb
->LastPossibleLBA
) {
713 // skip blocks beyond media boundary
714 if(lba
> Vcb
->LastPossibleLBA
) {
719 len
= Vcb
->LastPossibleLBA
- lba
;
722 // mark frag as XXX (see asUsed parameter)
727 if(lba
+j
> Vcb
->LastPossibleLBA
) {
729 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba
+j
));
732 if(!UDFGetUsedBit(Vcb
->FSBM_Bitmap
, lba
+j
)) {
734 AdPrint(("USED Mapping covers FREE block(s) @%x\n",lba
+j
));
743 if(lba
+j
> Vcb
->LastPossibleLBA
) {
745 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba
+j
));
748 if(!UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
+j
)) {
750 AdPrint(("FREE Mapping covers USED block(s) @%x\n",lba
+j
));
758 UDFReleaseResource(&(Vcb
->BitMapResource1
));
759 } // end UDFCheckSpaceAllocation_()
760 #endif //UDF_CHECK_DISK_ALLOCATION
763 UDFMarkBadSpaceAsUsed(
770 #define BIT_C (sizeof(Vcb->BSBM_Bitmap[0])*8)
771 len
= (lba
+len
+BIT_C
-1)/BIT_C
;
772 if(Vcb
->BSBM_Bitmap
) {
773 for(j
=lba
/BIT_C
; j
<len
; j
++) {
774 Vcb
->FSBM_Bitmap
[j
] &= ~Vcb
->BSBM_Bitmap
[j
];
778 } // UDFMarkBadSpaceAsUsed()
781 This routine marks space described by Mapping as Used/Freed (optionaly)
784 UDFMarkSpaceAsXXXNoProtect_(
788 #ifdef UDF_TRACK_ONDISK_ALLOCATION
790 IN uint32 BugCheckId
,
792 #endif //UDF_TRACK_ONDISK_ALLOCATION
796 uint32 lba
, j
, len
, BS
, BSh
;
798 BOOLEAN asUsed
= (asXXX
== AS_USED
|| (asXXX
& AS_BAD
));
799 #ifdef UDF_TRACK_ONDISK_ALLOCATION
800 BOOLEAN bit_before
, bit_after
;
801 #endif //UDF_TRACK_ONDISK_ALLOCATION
803 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
808 BSh
= Vcb
->BlockSizeBits
;
809 Vcb
->BitmapModified
= TRUE
;
811 // walk through all frags in data area specified
812 while(Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) {
813 if((Map
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
814 // skip unallocated frags
818 ASSERT(Map
[i
].extLocation
);
820 #ifdef UDF_TRACK_ONDISK_ALLOCATION
821 AdPrint(("Alloc:%x:%s:%x:@:%x:File:%x:Line:%d\n",
823 asUsed
? ((asXXX
& AS_BAD
) ? "B" : "U") : "F",
824 (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
,
829 #endif //UDF_TRACK_ONDISK_ALLOCATION
832 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
833 ASSERT(!(Map
[i
].extLength
& (BS
-1)));
834 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
835 // len = ((Map[i].extLength & UDF_EXTENT_LENGTH_MASK)+BS-1) >> BSh;
837 // len = (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh;
839 len
= ((Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)+BS
-1) >> BSh
;
840 lba
= Map
[i
].extLocation
;
841 if((lba
+len
) > Vcb
->LastPossibleLBA
) {
842 // skip blocks beyond media boundary
843 if(lba
> Vcb
->LastPossibleLBA
) {
848 len
= Vcb
->LastPossibleLBA
- lba
;
851 #ifdef UDF_TRACK_ONDISK_ALLOCATION
853 bit_before
= UDFGetBit(Vcb
->FSBM_Bitmap
, lba
-1);
854 bit_after
= UDFGetBit(Vcb
->FSBM_Bitmap
, lba
+len
);
855 #endif //UDF_TRACK_ONDISK_ALLOCATION
857 // mark frag as XXX (see asUsed parameter)
859 /* for(j=0;j<len;j++) {
860 UDFSetUsedBit(Vcb->FSBM_Bitmap, lba+j);
863 UDFSetUsedBits(Vcb
->FSBM_Bitmap
, lba
, len
);
864 #ifdef UDF_TRACK_ONDISK_ALLOCATION
866 ASSERT(UDFGetUsedBit(Vcb
->FSBM_Bitmap
, lba
+j
));
868 #endif //UDF_TRACK_ONDISK_ALLOCATION
871 // mark logical blocks in VAT as used
873 root
= UDFPartStart(Vcb
, UDFGetPartNumByPhysLba(Vcb
, lba
));
874 if((Vcb
->Vat
[lba
-root
+j
] == UDF_VAT_FREE_ENTRY
) &&
875 (lba
> Vcb
->LastLBA
)) {
876 Vcb
->Vat
[lba
-root
+j
] = 0x7fffffff;
881 /* for(j=0;j<len;j++) {
882 UDFSetFreeBit(Vcb->FSBM_Bitmap, lba+j);
885 UDFSetFreeBits(Vcb
->FSBM_Bitmap
, lba
, len
);
886 #ifdef UDF_TRACK_ONDISK_ALLOCATION
888 ASSERT(UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
+j
));
890 #endif //UDF_TRACK_ONDISK_ALLOCATION
892 UDFSetBits(Vcb
->BSBM_Bitmap
, lba
, len
);
894 UDFMarkBadSpaceAsUsed(Vcb
, lba
, len
);
896 if(asXXX
& AS_DISCARDED
) {
897 UDFUnmapRange(Vcb
, lba
, len
);
898 WCacheDiscardBlocks__(&(Vcb
->FastCache
), Vcb
, lba
, len
);
899 UDFSetZeroBits(Vcb
->ZSBM_Bitmap
, lba
, len
);
902 // mark logical blocks in VAT as free
903 // this operation can decrease resulting VAT size
905 root
= UDFPartStart(Vcb
, UDFGetPartNumByPhysLba(Vcb
, lba
));
906 Vcb
->Vat
[lba
-root
+j
] = UDF_VAT_FREE_ENTRY
;
909 // mark discarded extent as Not-Alloc-Not-Rec to
910 // prevent writes there
911 Map
[i
].extLength
= (len
<< BSh
) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
912 Map
[i
].extLocation
= 0;
915 #ifdef UDF_TRACK_ONDISK_ALLOCATION
917 ASSERT(bit_before
== UDFGetBit(Vcb
->FSBM_Bitmap
, lba
-1));
918 ASSERT(bit_after
== UDFGetBit(Vcb
->FSBM_Bitmap
, lba
+len
));
919 #endif //UDF_TRACK_ONDISK_ALLOCATION
923 } // end UDFMarkSpaceAsXXXNoProtect_()
926 This routine marks space described by Mapping as Used/Freed (optionaly)
927 It protects data with sync Resource
934 #ifdef UDF_TRACK_ONDISK_ALLOCATION
936 IN uint32 BugCheckId
,
938 #endif //UDF_TRACK_ONDISK_ALLOCATION
942 if(!Map
[0].extLength
) {
944 ASSERT(!Map
[0].extLocation
);
949 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
950 #ifdef UDF_TRACK_ONDISK_ALLOCATION
951 UDFMarkSpaceAsXXXNoProtect_(Vcb
, Map
, asXXX
, FE_lba
, BugCheckId
, Line
);
952 #else //UDF_TRACK_ONDISK_ALLOCATION
953 UDFMarkSpaceAsXXXNoProtect_(Vcb
, Map
, asXXX
);
954 #endif //UDF_TRACK_ONDISK_ALLOCATION
955 UDFReleaseResource(&(Vcb
->BitMapResource1
));
957 } // end UDFMarkSpaceAsXXX_()
959 #ifndef UDF_READ_ONLY_BUILD
961 This routine builds mapping for Length bytes in FreeSpace
962 It should be used when IN_ICB method is unavailable.
968 IN uint32 SearchStart
,
969 IN uint32 SearchLim
, // NOT included
970 OUT PEXTENT_INFO ExtInfo
,
972 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
975 #endif //UDF_TRACK_ALLOC_FREE_EXTENT
979 PEXTENT_MAP Map
= NULL
;
980 uint32 len
, LBS
, BSh
, blen
;
982 LBS
= Vcb
->LBlockSize
;
983 BSh
= Vcb
->BlockSizeBits
;
984 blen
= (uint32
)(((Length
+LBS
-1) & ~((int64
)LBS
-1)) >> BSh
);
985 ExtInfo
->Mapping
= NULL
;
988 ASSERT(blen
<= (uint32
)(UDF_MAX_EXTENT_LENGTH
>> BSh
));
990 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
992 if(blen
> (SearchLim
- SearchStart
)) {
993 goto no_free_space_err
;
995 // walk through the free space bitmap & find a single extent or a set of
996 // frags giving in sum the Length specified
998 Ext
.extLocation
= UDFFindMinSuitableExtent(Vcb
, blen
, SearchStart
,
999 SearchLim
, &len
, AllocFlags
);
1001 // ASSERT(len <= (uint32)(UDF_MAX_EXTENT_LENGTH >> BSh));
1004 Ext
.extLength
= blen
<<BSh
;
1007 // we need still some frags to complete request &
1008 // probably we have the opportunity to do it
1009 Ext
.extLength
= len
<<BSh
;
1013 // no more free space. abort
1014 if(ExtInfo
->Mapping
) {
1015 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // free
1016 MyFreePool__(ExtInfo
->Mapping
);
1017 ExtInfo
->Mapping
= NULL
;
1019 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1020 ExtInfo
->Length
= 0;//UDFGetExtentLength(ExtInfo->Mapping);
1021 AdPrint((" DISK_FULL\n"));
1022 return STATUS_DISK_FULL
;
1024 // append the frag found to mapping
1025 ASSERT(!(Ext
.extLength
>> 30));
1026 ASSERT(Ext
.extLocation
);
1028 // mark newly allocated blocks as zero-filled
1029 UDFSetZeroBits(Vcb
->ZSBM_Bitmap
, Ext
.extLocation
, (Ext
.extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
1031 if(AllocFlags
& EXTENT_FLAG_VERIFY
) {
1032 if(!UDFCheckArea(Vcb
, Ext
.extLocation
, Ext
.extLength
>> BSh
)) {
1033 AdPrint(("newly allocated extent contains BB\n"));
1034 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // free
1035 UDFMarkBadSpaceAsUsed(Vcb
, Ext
.extLocation
, Ext
.extLength
>> BSh
); // bad -> bad+used
1037 blen
+= Ext
.extLength
>>BSh
;
1042 Ext
.extLength
|= EXTENT_NOT_RECORDED_ALLOCATED
<< 30;
1043 if(!(ExtInfo
->Mapping
)) {
1045 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
1046 ExtInfo
->Mapping
= UDFExtentToMapping_(&Ext
, src
, line
);
1047 #else // UDF_TRACK_ALLOC_FREE_EXTENT
1048 ExtInfo
->Mapping
= UDFExtentToMapping(&Ext
);
1049 #endif // UDF_TRACK_ALLOC_FREE_EXTENT
1050 if(!ExtInfo
->Mapping
) {
1052 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1053 ExtInfo
->Length
= 0;
1054 return STATUS_INSUFFICIENT_RESOURCES
;
1056 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // used
1059 Map
= UDFExtentToMapping(&Ext
);
1062 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1063 ExtInfo
->Length
= UDFGetExtentLength(ExtInfo
->Mapping
);
1064 return STATUS_INSUFFICIENT_RESOURCES
;
1066 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, Map
, AS_USED
); // used
1067 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, Map
);
1070 if(!ExtInfo
->Mapping
) {
1072 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1073 ExtInfo
->Length
= 0;
1074 return STATUS_INSUFFICIENT_RESOURCES
;
1077 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1078 ExtInfo
->Length
= Length
;
1079 return STATUS_SUCCESS
;
1080 } // end UDFAllocFreeExtent_()
1081 #endif //UDF_READ_ONLY_BUILD
1088 UDFGetPartFreeSpace(
1093 uint32 lim
/*, len=1*/;
1096 PUCHAR cur
= (PUCHAR
)(Vcb
->FSBM_Bitmap
);
1098 lim
= (UDFPartEnd(Vcb
,partNum
)+7)/8;
1099 for(j
=(UDFPartStart(Vcb
,partNum
)+7)/8; j
<lim
/* && len*/; j
++) {
1100 s
+=bit_count_tab
[cur
[j
]];
1103 } // end UDFGetPartFreeSpace()
1113 // uint32* cur = (uint32*)(Vcb->FSBM_Bitmap);
1115 if(!Vcb
->CDR_Mode
&&
1116 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
)) {
1117 for(i
=0;i
<Vcb
->PartitionMaps
;i
++) {
1118 /* lim = UDFPartEnd(Vcb,i);
1119 for(j=UDFPartStart(Vcb,i); j<lim && len; ) {
1120 len = UDFGetBitmapLen(cur, j, lim);
1121 if(UDFGetFreeBit(cur, j)) // is the extent found free or used ?
1125 s
+= UDFGetPartFreeSpace(Vcb
, i
);
1128 ASSERT(Vcb
->LastPossibleLBA
>= max(Vcb
->NWA
, Vcb
->LastLBA
));
1129 s
= Vcb
->LastPossibleLBA
- max(Vcb
->NWA
, Vcb
->LastLBA
);
1130 //if(s & ((int64)1 << 64)) s=0;
1132 return s
>> Vcb
->LB2B_Bits
;
1133 } // end UDFGetFreeSpace()
1147 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
1148 s
= Vcb
->LastPossibleLBA
;
1149 } else if(!Vcb
->CDR_Mode
) {
1150 for(i
=0;i
<Vcb
->PartitionMaps
;i
++) {
1151 s
+=Vcb
->Partitions
[i
].PartitionLen
;
1154 if(s
& ((int64
)1 << 63)) s
=0; /* FIXME ReactOS this shift value was 64, which is undefiened behavior. */
1155 s
= Vcb
->LastPossibleLBA
- Vcb
->Partitions
[0].PartitionRoot
;
1157 return s
>> Vcb
->LB2B_Bits
;
1158 } // end UDFGetTotalSpace()
1162 returns Allocated and Zero-filled flags for given block
1163 any data in 'unallocated' blocks may be changed during flush process
1166 UDFIsBlockAllocated(
1174 if(!(((PVCB
)_Vcb
)->VCBFlags
& UDF_VCB_ASSUME_ALL_USED
)) {
1176 if((bm
= (uint32
*)(((PVCB
)_Vcb
)->FSBM_Bitmap
)))
1177 ret_val
= (UDFGetUsedBit(bm
, Lba
) ? WCACHE_BLOCK_USED
: 0);
1178 // check zero-filled
1179 if((bm
= (uint32
*)(((PVCB
)_Vcb
)->ZSBM_Bitmap
)))
1180 ret_val
|= (UDFGetZeroBit(bm
, Lba
) ? WCACHE_BLOCK_ZERO
: 0);
1182 ret_val
= WCACHE_BLOCK_USED
;
1186 // WCache works with LOGICAL addresses, not PHYSICAL, BB check must be performed UNDER cache
1188 if(bm = (uint32*)(((PVCB)_Vcb)->BSBM_Bitmap)) {
1189 ret_val |= (UDFGetBadBit(bm, Lba) ? WCACHE_BLOCK_BAD : 0);
1190 if(ret_val & WCACHE_BLOCK_BAD) {
1191 KdPrint(("Marked BB @ %#x\n", Lba));
1196 } // end UDFIsBlockAllocated()
1201 #pragma warning(disable:4035) // re-enable below
1210 IN uint32
* arr
, // ECX
1211 IN uint32 bit
// EDX
1215 // ASSERT(bit < 300000);
1224 add eax
,ecx
// eax+arr
1236 return ((BOOLEAN
)(((((uint32
*)(arr
))[(bit
)>>5]) >> ((bit
)&31)) &1));
1238 } // end UDFGetBit__()
1246 IN uint32
* arr
, // ECX
1247 IN uint32 bit
// EDX
1251 // ASSERT(bit < 300000);
1261 add eax
,ecx
// eax+arr
1274 (((uint32
*)(arr
))[(bit
)>>5]) |= (((uint32
)1) << ((bit
)&31));
1276 } // end UDFSetBit__()
1308 jnz
short sb_loop_cont
1311 jb
short sb_loop_cont
1313 mov
[dword ptr esi
+eax
],0xffffffff
1329 jnz
short sb_loop_cont
1343 UDFSetBit(arr
, bit
+j
);
1346 } // end UDFSetBits__()
1354 IN uint32
* arr
, // ECX
1355 IN uint32 bit
// EDX
1359 // ASSERT(bit < 300000);
1369 add eax
,ecx
// eax+arr
1382 (((uint32
*)(arr
))[(bit
)>>5]) &= (~(((uint32
)1) << ((bit
)&31)));
1384 } // end UDFClrBit__()
1416 jnz
short cp_loop_cont
1419 jb
short cp_loop_cont
1421 mov
[dword ptr esi
+eax
],0x00000000
1437 jnz
short cp_loop_cont
1451 UDFClrBit(arr
, bit
+j
);
1454 } // end UDFClrBits__()
1457 #pragma warning(default:4035)