1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 ////////////////////////////////////////////////////////////////////
12 This file contains filesystem-specific routines
13 responsible for disk space management
19 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_ALLOC
21 static const int8 bit_count_tab
[] = {
22 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
23 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
24 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
25 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
26 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
27 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
28 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
29 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
31 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
32 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
33 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
34 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
35 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
36 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
37 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
38 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
42 This routine converts physical address to logical in specified partition
51 PUDFPartMap pm
= Vcb
->Partitions
;
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.
333 uint32 Lim
// NOT included
346 xor edx
,edx
// init bit-counter
347 mov ebx
,[ebp
+0x08] // set base pointer in EBX (Bitmap)
348 mov esi
,[ebp
+0x0c] // set Offs in ESI
349 mov edi
,[ebp
+0x10] // set Lim in EDI
351 // check if Lim <= Offs
361 // set 1st bit number in CL
364 // make ESI uint32-index
367 // save last bit number in CH
371 // make EDI uint32-index of the last uint32
380 /* COUNT 1-BITS SECTION */
384 ja exit_count
// must never happen
429 /* COUNT 0-BITS SECTION */
433 ja exit_count
// must never happen
493 #else // NO X86 optimization , use generic C/C++
500 uint32 Lim
// NOT included
505 return 0;//(Offs == Lim);
508 BOOLEAN bit
= UDFGetBit(Bitmap
, Offs
);
511 uint8 j
=(uint8
)(Offs
&31);
512 uint8 lLim
=(uint8
)(Lim
&31);
516 ASSERT((bit
== 0) || (bit
== 1));
524 while( j
< ((i
<Lim
) ? 32 : lLim
) ) {
525 if( ((BOOLEAN
)(a
&1)) != bit
)
537 if((bit
&& (a
==0xffffffff)) ||
549 } // end UDFGetBitmapLen()
551 #ifndef UDF_READ_ONLY_BUILD
553 This routine scans disc free space Bitmap for minimal suitable extent.
554 It returns maximal available extent if no long enough extents found.
557 UDFFindMinSuitableExtent(
559 IN uint32 Length
, // in blocks
560 IN uint32 SearchStart
,
561 IN uint32 SearchLim
, // NOT included
562 OUT uint32
* MaxExtLen
,
572 BOOLEAN align
= FALSE
;
573 uint32 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
575 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
577 // we'll try to allocate packet-aligned block at first
578 if(!(Length
& (PS
-1)) && !Vcb
->CDR_Mode
&& (Length
>= PS
*2))
580 if(AllocFlags
& EXTENT_FLAG_ALLOC_SEQUENTIAL
)
582 if(Length
> (uint32
)(UDF_MAX_EXTENT_LENGTH
>> Vcb
->BlockSizeBits
))
583 Length
= (UDF_MAX_EXTENT_LENGTH
>> Vcb
->BlockSizeBits
);
584 // align Length according to _Logical_ block size & convert it to BCount
585 i
= (1<<Vcb
->LB2B_Bits
)-1;
586 Length
= (Length
+i
) & ~i
;
587 cur
= (uint32
*)(Vcb
->FSBM_Bitmap
);
594 ASSERT(i
<= SearchLim
);
596 i
= (i
+PS
-1) & ~(PS
-1);
597 ASSERT(i
<= SearchLim
);
601 len
= UDFGetBitmapLen(cur
, i
, SearchLim
);
602 if(UDFGetFreeBit(cur
, i
)) { // is the extent found free or used ?
605 // minimize extent length
606 if(!best_len
|| (best_len
> len
)) {
613 // remember max extent
619 // if this is CD-R mode, we should not think about fragmentation
620 // due to CD-R nature file will be fragmented in any case
621 if(Vcb
->CDR_Mode
) break;
625 // if we can't find suitable Packet-size aligned block,
626 // retry without any alignment requirements
627 if(!best_len
&& align
) {
632 // minimal suitable block
633 (*MaxExtLen
) = best_len
;
637 (*MaxExtLen
) = max_len
;
639 } // end UDFFindMinSuitableExtent()
640 #endif //UDF_READ_ONLY_BUILD
642 #ifdef UDF_CHECK_DISK_ALLOCATION
644 This routine checks space described by Mapping as Used/Freed (optionaly)
647 UDFCheckSpaceAllocation_(
651 #ifdef UDF_TRACK_ONDISK_ALLOCATION
653 IN uint32 BugCheckId
,
655 #endif //UDF_TRACK_ONDISK_ALLOCATION
659 uint32 lba
, j
, len
, BS
, BSh
;
660 BOOLEAN asUsed
= (asXXX
== AS_USED
);
665 BSh
= Vcb
->BlockSizeBits
;
667 UDFAcquireResourceShared(&(Vcb
->BitMapResource1
),TRUE
);
668 // walk through all frags in data area specified
669 #ifdef UDF_TRACK_ONDISK_ALLOCATION
670 AdPrint(("ChkAlloc:Map:%x:File:%x:Line:%d\n",
675 #endif //UDF_TRACK_ONDISK_ALLOCATION
676 while(Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) {
678 #ifdef UDF_TRACK_ONDISK_ALLOCATION
679 AdPrint(("ChkAlloc:%x:%s:%x:@:%x:(%x):File:%x:Line:%d\n",
682 (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
,
684 (Map
[i
].extLength
>> 30),
688 #endif //UDF_TRACK_ONDISK_ALLOCATION
690 UDFCheckUsedBitOwner(Vcb
, (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
, FE_lba
);
692 UDFCheckFreeBitOwner(Vcb
, (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
695 if((Map
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
696 // skip unallocated frags
697 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
698 ASSERT(!Map
[i
].extLocation
);
702 // ASSERT(!(Map[i].extLength & UDF_EXTENT_LENGTH_MASK));
703 ASSERT(Map
[i
].extLocation
);
706 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
707 ASSERT(!(Map
[i
].extLength
& (BS
-1)));
708 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
709 len
= ((Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)+BS
-1) >> BSh
;
710 lba
= Map
[i
].extLocation
;
711 if((lba
+len
) > Vcb
->LastPossibleLBA
) {
712 // skip blocks beyond media boundary
713 if(lba
> Vcb
->LastPossibleLBA
) {
718 len
= Vcb
->LastPossibleLBA
- lba
;
721 // mark frag as XXX (see asUsed parameter)
726 if(lba
+j
> Vcb
->LastPossibleLBA
) {
728 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba
+j
));
731 if(!UDFGetUsedBit(Vcb
->FSBM_Bitmap
, lba
+j
)) {
733 AdPrint(("USED Mapping covers FREE block(s) @%x\n",lba
+j
));
742 if(lba
+j
> Vcb
->LastPossibleLBA
) {
744 AdPrint(("USED Mapping covers block(s) beyond media @%x\n",lba
+j
));
747 if(!UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
+j
)) {
749 AdPrint(("FREE Mapping covers USED block(s) @%x\n",lba
+j
));
757 UDFReleaseResource(&(Vcb
->BitMapResource1
));
758 } // end UDFCheckSpaceAllocation_()
759 #endif //UDF_CHECK_DISK_ALLOCATION
762 UDFMarkBadSpaceAsUsed(
769 #define BIT_C (sizeof(Vcb->BSBM_Bitmap[0])*8)
770 len
= (lba
+len
+BIT_C
-1)/BIT_C
;
771 if(Vcb
->BSBM_Bitmap
) {
772 for(j
=lba
/BIT_C
; j
<len
; j
++) {
773 Vcb
->FSBM_Bitmap
[j
] &= ~Vcb
->BSBM_Bitmap
[j
];
777 } // UDFMarkBadSpaceAsUsed()
780 This routine marks space described by Mapping as Used/Freed (optionaly)
783 UDFMarkSpaceAsXXXNoProtect_(
787 #ifdef UDF_TRACK_ONDISK_ALLOCATION
789 IN uint32 BugCheckId
,
791 #endif //UDF_TRACK_ONDISK_ALLOCATION
795 uint32 lba
, j
, len
, BS
, BSh
;
797 BOOLEAN asUsed
= (asXXX
== AS_USED
|| (asXXX
& AS_BAD
));
798 #ifdef UDF_TRACK_ONDISK_ALLOCATION
799 BOOLEAN bit_before
, bit_after
;
800 #endif //UDF_TRACK_ONDISK_ALLOCATION
802 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
807 BSh
= Vcb
->BlockSizeBits
;
808 Vcb
->BitmapModified
= TRUE
;
810 // walk through all frags in data area specified
811 while(Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) {
812 if((Map
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
813 // skip unallocated frags
817 ASSERT(Map
[i
].extLocation
);
819 #ifdef UDF_TRACK_ONDISK_ALLOCATION
820 AdPrint(("Alloc:%x:%s:%x:@:%x:File:%x:Line:%d\n",
822 asUsed
? ((asXXX
& AS_BAD
) ? "B" : "U") : "F",
823 (Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
,
828 #endif //UDF_TRACK_ONDISK_ALLOCATION
831 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
832 ASSERT(!(Map
[i
].extLength
& (BS
-1)));
833 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
834 // len = ((Map[i].extLength & UDF_EXTENT_LENGTH_MASK)+BS-1) >> BSh;
836 // len = (Map[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh;
838 len
= ((Map
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)+BS
-1) >> BSh
;
839 lba
= Map
[i
].extLocation
;
840 if((lba
+len
) > Vcb
->LastPossibleLBA
) {
841 // skip blocks beyond media boundary
842 if(lba
> Vcb
->LastPossibleLBA
) {
847 len
= Vcb
->LastPossibleLBA
- lba
;
850 #ifdef UDF_TRACK_ONDISK_ALLOCATION
852 bit_before
= UDFGetBit(Vcb
->FSBM_Bitmap
, lba
-1);
853 bit_after
= UDFGetBit(Vcb
->FSBM_Bitmap
, lba
+len
);
854 #endif //UDF_TRACK_ONDISK_ALLOCATION
856 // mark frag as XXX (see asUsed parameter)
858 /* for(j=0;j<len;j++) {
859 UDFSetUsedBit(Vcb->FSBM_Bitmap, lba+j);
862 UDFSetUsedBits(Vcb
->FSBM_Bitmap
, lba
, len
);
863 #ifdef UDF_TRACK_ONDISK_ALLOCATION
865 ASSERT(UDFGetUsedBit(Vcb
->FSBM_Bitmap
, lba
+j
));
867 #endif //UDF_TRACK_ONDISK_ALLOCATION
870 // mark logical blocks in VAT as used
872 root
= UDFPartStart(Vcb
, UDFGetPartNumByPhysLba(Vcb
, lba
));
873 if((Vcb
->Vat
[lba
-root
+j
] == UDF_VAT_FREE_ENTRY
) &&
874 (lba
> Vcb
->LastLBA
)) {
875 Vcb
->Vat
[lba
-root
+j
] = 0x7fffffff;
880 /* for(j=0;j<len;j++) {
881 UDFSetFreeBit(Vcb->FSBM_Bitmap, lba+j);
884 UDFSetFreeBits(Vcb
->FSBM_Bitmap
, lba
, len
);
885 #ifdef UDF_TRACK_ONDISK_ALLOCATION
887 ASSERT(UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
+j
));
889 #endif //UDF_TRACK_ONDISK_ALLOCATION
891 UDFSetBits(Vcb
->BSBM_Bitmap
, lba
, len
);
893 UDFMarkBadSpaceAsUsed(Vcb
, lba
, len
);
895 if(asXXX
& AS_DISCARDED
) {
896 UDFUnmapRange(Vcb
, lba
, len
);
897 WCacheDiscardBlocks__(&(Vcb
->FastCache
), Vcb
, lba
, len
);
898 UDFSetZeroBits(Vcb
->ZSBM_Bitmap
, lba
, len
);
901 // mark logical blocks in VAT as free
902 // this operation can decrease resulting VAT size
904 root
= UDFPartStart(Vcb
, UDFGetPartNumByPhysLba(Vcb
, lba
));
905 Vcb
->Vat
[lba
-root
+j
] = UDF_VAT_FREE_ENTRY
;
908 // mark discarded extent as Not-Alloc-Not-Rec to
909 // prevent writes there
910 Map
[i
].extLength
= (len
<< BSh
) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
911 Map
[i
].extLocation
= 0;
914 #ifdef UDF_TRACK_ONDISK_ALLOCATION
916 ASSERT(bit_before
== UDFGetBit(Vcb
->FSBM_Bitmap
, lba
-1));
917 ASSERT(bit_after
== UDFGetBit(Vcb
->FSBM_Bitmap
, lba
+len
));
918 #endif //UDF_TRACK_ONDISK_ALLOCATION
922 } // end UDFMarkSpaceAsXXXNoProtect_()
925 This routine marks space described by Mapping as Used/Freed (optionaly)
926 It protects data with sync Resource
933 #ifdef UDF_TRACK_ONDISK_ALLOCATION
935 IN uint32 BugCheckId
,
937 #endif //UDF_TRACK_ONDISK_ALLOCATION
941 if(!Map
[0].extLength
) {
943 ASSERT(!Map
[0].extLocation
);
948 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
949 #ifdef UDF_TRACK_ONDISK_ALLOCATION
950 UDFMarkSpaceAsXXXNoProtect_(Vcb
, Map
, asXXX
, FE_lba
, BugCheckId
, Line
);
951 #else //UDF_TRACK_ONDISK_ALLOCATION
952 UDFMarkSpaceAsXXXNoProtect_(Vcb
, Map
, asXXX
);
953 #endif //UDF_TRACK_ONDISK_ALLOCATION
954 UDFReleaseResource(&(Vcb
->BitMapResource1
));
956 } // end UDFMarkSpaceAsXXX_()
958 #ifndef UDF_READ_ONLY_BUILD
960 This routine builds mapping for Length bytes in FreeSpace
961 It should be used when IN_ICB method is unavailable.
967 IN uint32 SearchStart
,
968 IN uint32 SearchLim
, // NOT included
969 OUT PEXTENT_INFO ExtInfo
,
971 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
974 #endif //UDF_TRACK_ALLOC_FREE_EXTENT
978 PEXTENT_MAP Map
= NULL
;
979 uint32 len
, LBS
, BSh
, blen
;
981 LBS
= Vcb
->LBlockSize
;
982 BSh
= Vcb
->BlockSizeBits
;
983 blen
= (uint32
)(((Length
+LBS
-1) & ~((int64
)LBS
-1)) >> BSh
);
984 ExtInfo
->Mapping
= NULL
;
987 ASSERT(blen
<= (uint32
)(UDF_MAX_EXTENT_LENGTH
>> BSh
));
989 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
991 if(blen
> (SearchLim
- SearchStart
)) {
992 goto no_free_space_err
;
994 // walk through the free space bitmap & find a single extent or a set of
995 // frags giving in sum the Length specified
997 Ext
.extLocation
= UDFFindMinSuitableExtent(Vcb
, blen
, SearchStart
,
998 SearchLim
, &len
, AllocFlags
);
1000 // ASSERT(len <= (uint32)(UDF_MAX_EXTENT_LENGTH >> BSh));
1003 Ext
.extLength
= blen
<<BSh
;
1006 // we need still some frags to complete request &
1007 // probably we have the opportunity to do it
1008 Ext
.extLength
= len
<<BSh
;
1012 // no more free space. abort
1013 if(ExtInfo
->Mapping
) {
1014 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // free
1015 MyFreePool__(ExtInfo
->Mapping
);
1016 ExtInfo
->Mapping
= NULL
;
1018 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1019 ExtInfo
->Length
= 0;//UDFGetExtentLength(ExtInfo->Mapping);
1020 AdPrint((" DISK_FULL\n"));
1021 return STATUS_DISK_FULL
;
1023 // append the frag found to mapping
1024 ASSERT(!(Ext
.extLength
>> 30));
1025 ASSERT(Ext
.extLocation
);
1027 // mark newly allocated blocks as zero-filled
1028 UDFSetZeroBits(Vcb
->ZSBM_Bitmap
, Ext
.extLocation
, (Ext
.extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
1030 if(AllocFlags
& EXTENT_FLAG_VERIFY
) {
1031 if(!UDFCheckArea(Vcb
, Ext
.extLocation
, Ext
.extLength
>> BSh
)) {
1032 AdPrint(("newly allocated extent contains BB\n"));
1033 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // free
1034 UDFMarkBadSpaceAsUsed(Vcb
, Ext
.extLocation
, Ext
.extLength
>> BSh
); // bad -> bad+used
1036 blen
+= Ext
.extLength
>>BSh
;
1041 Ext
.extLength
|= EXTENT_NOT_RECORDED_ALLOCATED
<< 30;
1042 if(!(ExtInfo
->Mapping
)) {
1044 #ifdef UDF_TRACK_ALLOC_FREE_EXTENT
1045 ExtInfo
->Mapping
= UDFExtentToMapping_(&Ext
, src
, line
);
1046 #else // UDF_TRACK_ALLOC_FREE_EXTENT
1047 ExtInfo
->Mapping
= UDFExtentToMapping(&Ext
);
1048 #endif // UDF_TRACK_ALLOC_FREE_EXTENT
1049 if(!ExtInfo
->Mapping
) {
1051 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1052 ExtInfo
->Length
= 0;
1053 return STATUS_INSUFFICIENT_RESOURCES
;
1055 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // used
1058 Map
= UDFExtentToMapping(&Ext
);
1061 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1062 ExtInfo
->Length
= UDFGetExtentLength(ExtInfo
->Mapping
);
1063 return STATUS_INSUFFICIENT_RESOURCES
;
1065 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, Map
, AS_USED
); // used
1066 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, Map
);
1069 if(!ExtInfo
->Mapping
) {
1071 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1072 ExtInfo
->Length
= 0;
1073 return STATUS_INSUFFICIENT_RESOURCES
;
1076 UDFReleaseResource(&(Vcb
->BitMapResource1
));
1077 ExtInfo
->Length
= Length
;
1078 return STATUS_SUCCESS
;
1079 } // end UDFAllocFreeExtent_()
1080 #endif //UDF_READ_ONLY_BUILD
1087 UDFGetPartFreeSpace(
1092 uint32 lim
/*, len=1*/;
1095 PUCHAR cur
= (PUCHAR
)(Vcb
->FSBM_Bitmap
);
1097 lim
= (UDFPartEnd(Vcb
,partNum
)+7)/8;
1098 for(j
=(UDFPartStart(Vcb
,partNum
)+7)/8; j
<lim
/* && len*/; j
++) {
1099 s
+=bit_count_tab
[cur
[j
]];
1102 } // end UDFGetPartFreeSpace()
1112 // uint32* cur = (uint32*)(Vcb->FSBM_Bitmap);
1114 if(!Vcb
->CDR_Mode
&&
1115 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
)) {
1116 for(i
=0;i
<Vcb
->PartitionMaps
;i
++) {
1117 /* lim = UDFPartEnd(Vcb,i);
1118 for(j=UDFPartStart(Vcb,i); j<lim && len; ) {
1119 len = UDFGetBitmapLen(cur, j, lim);
1120 if(UDFGetFreeBit(cur, j)) // is the extent found free or used ?
1124 s
+= UDFGetPartFreeSpace(Vcb
, i
);
1127 ASSERT(Vcb
->LastPossibleLBA
>= max(Vcb
->NWA
, Vcb
->LastLBA
));
1128 s
= Vcb
->LastPossibleLBA
- max(Vcb
->NWA
, Vcb
->LastLBA
);
1129 //if(s & ((int64)1 << 64)) s=0;
1131 return s
>> Vcb
->LB2B_Bits
;
1132 } // end UDFGetFreeSpace()
1146 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
1147 s
= Vcb
->LastPossibleLBA
;
1148 } else if(!Vcb
->CDR_Mode
) {
1149 for(i
=0;i
<Vcb
->PartitionMaps
;i
++) {
1150 s
+=Vcb
->Partitions
[i
].PartitionLen
;
1153 if(s
& ((int64
)1 << 64)) s
=0;
1154 s
= Vcb
->LastPossibleLBA
- Vcb
->Partitions
[0].PartitionRoot
;
1156 return s
>> Vcb
->LB2B_Bits
;
1157 } // end UDFGetTotalSpace()
1161 returns Allocated and Zero-filled flags for given block
1162 any data in 'unallocated' blocks may be changed during flush process
1165 UDFIsBlockAllocated(
1173 if(!(((PVCB
)_Vcb
)->VCBFlags
& UDF_VCB_ASSUME_ALL_USED
)) {
1175 if((bm
= (uint32
*)(((PVCB
)_Vcb
)->FSBM_Bitmap
)))
1176 ret_val
= (UDFGetUsedBit(bm
, Lba
) ? WCACHE_BLOCK_USED
: 0);
1177 // check zero-filled
1178 if((bm
= (uint32
*)(((PVCB
)_Vcb
)->ZSBM_Bitmap
)))
1179 ret_val
|= (UDFGetZeroBit(bm
, Lba
) ? WCACHE_BLOCK_ZERO
: 0);
1181 ret_val
= WCACHE_BLOCK_USED
;
1185 // WCache works with LOGICAL addresses, not PHYSICAL, BB check must be performed UNDER cache
1187 if(bm = (uint32*)(((PVCB)_Vcb)->BSBM_Bitmap)) {
1188 ret_val |= (UDFGetBadBit(bm, Lba) ? WCACHE_BLOCK_BAD : 0);
1189 if(ret_val & WCACHE_BLOCK_BAD) {
1190 KdPrint(("Marked BB @ %#x\n", Lba));
1195 } // end UDFIsBlockAllocated()
1199 #pragma warning(disable:4035) // re-enable below
1205 IN uint32
* arr
, // ECX
1206 IN uint32 bit
// EDX
1210 // ASSERT(bit < 300000);
1219 add eax
,ecx
// eax+arr
1231 return ((BOOLEAN
)(((((uint32
*)(arr
))[(bit
)>>5]) >> ((bit
)&31)) &1));
1233 } // end UDFGetBit__()
1239 IN uint32
* arr
, // ECX
1240 IN uint32 bit
// EDX
1244 // ASSERT(bit < 300000);
1254 add eax
,ecx
// eax+arr
1267 (((uint32
*)(arr
))[(bit
)>>5]) |= (((uint32
)1) << ((bit
)&31));
1269 } // end UDFSetBit__()
1301 jnz
short sb_loop_cont
1304 jb
short sb_loop_cont
1306 mov
[dword ptr esi
+eax
],0xffffffff
1322 jnz
short sb_loop_cont
1336 UDFSetBit(arr
, bit
+j
);
1339 } // end UDFSetBits__()
1345 IN uint32
* arr
, // ECX
1346 IN uint32 bit
// EDX
1350 // ASSERT(bit < 300000);
1360 add eax
,ecx
// eax+arr
1373 (((uint32
*)(arr
))[(bit
)>>5]) &= (~(((uint32
)1) << ((bit
)&31)));
1375 } // end UDFClrBit__()
1407 jnz
short cp_loop_cont
1410 jb
short cp_loop_cont
1412 mov
[dword ptr esi
+eax
],0x00000000
1428 jnz
short cp_loop_cont
1442 UDFClrBit(arr
, bit
+j
);
1445 } // end UDFClrBits__()
1447 #pragma warning(default:4035)