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 extent & mapping management
20 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_EXTENT
23 This routine converts offset in extent to Lba & returns offset in the 1st
24 sector & bytes before end of block.
25 Here we assume no references to AllocDescs
30 IN PEXTENT_MAP Extent
, // Extent array
31 IN int64 Offset
, // offset in extent
32 OUT uint32
* SectorOffset
,
33 OUT uint32
* AvailLength
, // available data in this block
38 uint32 j
=0, l
, d
, BSh
= Vcb
->BlockSizeBits
;
40 uint32 i
=0, BOffset
; // block nums
42 BOffset
= (uint32
)(Offset
>> BSh
);
43 // scan extent table for suitable range (frag)
44 ExtPrint(("ExtLen %x\n", Extent
->extLength
));
45 while(i
+(d
= (l
= (Extent
->extLength
& UDF_EXTENT_LENGTH_MASK
)) >> BSh
) <= BOffset
) {
48 if(Index
) (*Index
) = j
-1;
51 (*Flags
) = (Extent
->extLength
>> 30);
53 return LBA_OUT_OF_EXTENT
;
62 Offs
= (*((uint32
*)&Offset
)) - (i
<< BSh
); // offset in frag
65 (*SectorOffset
) = Offs
& (Vcb
->BlockSize
-1);// offset in 1st Lba
67 (*AvailLength
) = l
- Offs
;// bytes to EO frag
69 (*Flags
) = (Extent
->extLength
>> 30);
73 ASSERT(((Extent
->extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) || Extent
->extLocation
);
75 return Extent
->extLocation
+ BOffset
;// 1st Lba
76 } // end UDFExtentOffsetToLba()
81 IN PEXTENT_MAP Extent
, // Extent array
82 OUT uint32
* AvailLength
, // available data in this block
92 // scan extent table for suitable range (frag)
93 // d = (l = (Extent->extLength & UDF_EXTENT_LENGTH_MASK));
94 l
= (Extent
->extLength
& UDF_EXTENT_LENGTH_MASK
);
99 (*Flags
) = (Extent
->extLength
>> 30);
100 return LBA_OUT_OF_EXTENT
;
104 (*AvailLength
) = l
;// bytes to EO frag
105 (*Flags
) = (Extent
->extLength
>> 30);
107 ASSERT(((*Flags
) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) || Extent
->extLocation
);
109 return Extent
->extLocation
;// 1st Lba
110 } // end UDFNextExtentToLba()
113 This routine locates frag containing specified Lba in extent
116 UDFLocateLbaInExtent(
118 IN PEXTENT_MAP Extent
, // Extent array
122 uint32 l
, BSh
= Vcb
->BlockSizeBits
;
125 while((l
= ((Extent
->extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
))) {
127 if(Extent
->extLocation
>= lba
&&
128 Extent
->extLocation
+l
< lba
) {
134 return LBA_OUT_OF_EXTENT
;// index of item in extent, containing out Lba
135 } // end UDFLocateLbaInExtent()
138 This routine calculates total length of specified extent.
139 Here we assume no references to AllocDescs
143 IN PEXTENT_MAP Extent
// Extent array
146 if(!Extent
) return 0;
149 #if defined (_X86_) && defined (_MSC_VER)
159 __asm mov eax
,[esi
+ecx
*8] // Extent[j].extLength
160 __asm
and eax
,UDF_EXTENT_LENGTH_MASK
171 #else // NO X86 optimization , use generic C/C++
173 while(Extent
->extLength
) {
174 i
+= (Extent
->extLength
& UDF_EXTENT_LENGTH_MASK
);
181 } // UDFGetExtentLength()
184 This routine appends Zero-terminator to single Extent-entry.
185 Such operation makes it compatible with other internal routines
191 #ifdef UDF_TRACK_EXTENT_TO_MAPPING
194 #endif //UDF_TRACK_EXTENT_TO_MAPPING
199 #ifdef UDF_TRACK_EXTENT_TO_MAPPING
200 #define UDF_EXT_MAP_MULT 4
201 #else //UDF_TRACK_EXTENT_TO_MAPPING
202 #define UDF_EXT_MAP_MULT 2
203 #endif //UDF_TRACK_EXTENT_TO_MAPPING
205 Map
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDF_EXT_MAP_MULT
*
206 sizeof(EXTENT_MAP
), MEM_EXTMAP_TAG
);
207 if(!Map
) return NULL
;
208 RtlZeroMemory((int8
*)(Map
+1), sizeof(EXTENT_MAP
));
209 Map
[0].extLength
= Extent
->extLength
;
210 Map
[0].extLocation
= Extent
->extLocation
;
211 #ifdef UDF_TRACK_EXTENT_TO_MAPPING
212 Map
[2].extLength
= src
;
213 Map
[2].extLocation
= line
;
214 #endif //UDF_TRACK_EXTENT_TO_MAPPING
216 } // end UDFExtentToMapping()
219 This routine calculates file mapping length (in bytes) including
224 IN PEXTENT_MAP Extent
227 if(!Extent
) return 0;
230 #if defined (_X86_) && defined (_MSC_VER)
236 __asm mov ecx
,[ebx
+eax
*8]
247 #else // NO X86 optimization , use generic C/C++
249 while(Extent
->extLength
) {
254 i
*=sizeof(EXTENT_MAP
);
258 return i
; // i*sizeof(EXTENT_MAP)
259 } // end UDFGetMappingLength()
262 This routine merges 2 sequencial file mappings
267 IN PEXTENT_MAP Extent
,
268 IN PEXTENT_MAP Extent2
274 len
= UDFGetMappingLength(Extent
);
275 len2
= UDFGetMappingLength(Extent2
);
280 if(MyReallocPool__((int8
*)Extent
, len
, (int8
**)(&NewExt
), len
+len2
-sizeof(EXTENT_MAP
))) {
281 RtlCopyMemory(((int8
*)NewExt
)+len
-sizeof(EXTENT_MAP
), (int8
*)Extent2
, len2
);
283 ExtPrint(("UDFMergeMappings failed\n"));
287 } // end UDFMergeMappings()
290 This routine builds file mapping according to ShortAllocDesc (SHORT_AD)
294 UDFShortAllocDescToMapping(
297 IN PSHORT_AD AllocDesc
,
298 IN uint32 AllocDescLength
,
299 IN uint32 SubCallCount
,
300 OUT PEXTENT_INFO AllocLoc
303 uint32 i
, lim
, l
, len
, type
;
305 PEXTENT_MAP Extent
, Extent2
, AllocMap
;
307 PALLOC_EXT_DESC NextAllocDesc
;
310 EXTENT_INFO NextAllocLoc
;
311 BOOLEAN w2k_compat
= FALSE
;
313 ExtPrint(("UDFShortAllocDescToMapping: len=%x\n", AllocDescLength
));
315 if(SubCallCount
> ALLOC_DESC_MAX_RECURSE
) return NULL
;
317 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
318 // BSh = Vcb->BlockSizeBits;
319 l
= ((lim
= (AllocDescLength
/sizeof(SHORT_AD
))) + 1 ) * sizeof(EXTENT_AD
);
320 Extent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, l
, MEM_EXTMAP_TAG
);
321 if(!Extent
) return NULL
;
323 NextAllocLoc
.Offset
= 0;
326 type
= AllocDesc
[i
].extLength
>> 30;
327 len
= AllocDesc
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
328 ExtPrint(("ShExt: type %x, loc %x, len %x\n", type
, AllocDesc
[i
].extPosition
, len
));
329 if(type
== EXTENT_NEXT_EXTENT_ALLOCDESC
) {
330 // read next frag of allocation descriptors if encountered
331 if(len
< sizeof(ALLOC_EXT_DESC
)) {
332 MyFreePool__(Extent
);
335 NextAllocDesc
= (PALLOC_EXT_DESC
)MyAllocatePoolTag__(NonPagedPool
, len
, MEM_ALLOCDESC_TAG
);
337 MyFreePool__(Extent
);
340 // record information about this frag
341 locAddr
.logicalBlockNum
= AllocDesc
[i
].extPosition
;
342 AllocExt
.extLength
= len
;
343 AllocExt
.extLocation
= UDFPartLbaToPhys(Vcb
, &locAddr
);
344 if(AllocExt
.extLocation
== LBA_OUT_OF_EXTENT
) {
345 KdPrint(("bad address\n"));
346 MyFreePool__(NextAllocDesc
);
347 MyFreePool__(Extent
);
350 NextAllocLoc
.Mapping
=
351 AllocMap
= UDFExtentToMapping(&AllocExt
);
352 NextAllocLoc
.Length
= len
;
354 MyFreePool__(NextAllocDesc
);
355 MyFreePool__(Extent
);
358 AllocLoc
->Mapping
= UDFMergeMappings(AllocLoc
->Mapping
, AllocMap
);
359 if(!AllocLoc
->Mapping
||
361 !OS_SUCCESS(UDFReadExtent(Vcb
, &NextAllocLoc
,
362 0, len
, FALSE
, (int8
*)NextAllocDesc
, &ReadBytes
)))
364 MyFreePool__(AllocMap
);
365 MyFreePool__(NextAllocDesc
);
366 MyFreePool__(Extent
);
369 MyFreePool__(AllocMap
);
371 if((NextAllocDesc
->descTag
.tagIdent
!= TID_ALLOC_EXTENT_DESC
) ||
372 (NextAllocDesc
->lengthAllocDescs
> (len
- sizeof(ALLOC_EXT_DESC
))) ) {
373 KdPrint(("Integrity check failed\n"));
374 KdPrint(("NextAllocDesc->descTag.tagIdent = %x\n", NextAllocDesc
->descTag
.tagIdent
));
375 KdPrint(("NextAllocDesc->lengthAllocDescs = %x\n", NextAllocDesc
->lengthAllocDescs
));
376 KdPrint(("len = %x\n", len
));
377 MyFreePool__(NextAllocDesc
);
378 MyFreePool__(Extent
);
381 // perform recursive call to obtain mapping
382 NextAllocLoc
.Flags
= 0;
383 Extent2
= UDFShortAllocDescToMapping(Vcb
, PartNum
, (PSHORT_AD
)(NextAllocDesc
+1),
384 NextAllocDesc
->lengthAllocDescs
, SubCallCount
+1, AllocLoc
);
386 MyFreePool__(NextAllocDesc
);
387 MyFreePool__(Extent
);
390 UDFCheckSpaceAllocation(Vcb
, 0, Extent2
, AS_USED
); // check if used
391 // and merge this 2 mappings into 1
392 Extent
[i
].extLength
= 0;
393 Extent
[i
].extLocation
= 0;
394 Extent
= UDFMergeMappings(Extent
, Extent2
);
396 if(NextAllocLoc
.Flags
& EXTENT_FLAG_2K_COMPAT
) {
397 ExtPrint(("w2k-compat\n"));
398 AllocLoc
->Flags
|= EXTENT_FLAG_2K_COMPAT
;
401 MyFreePool__(Extent2
);
405 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
406 ASSERT(!(len
& (Vcb
->LBlockSize
-1) ));
407 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
408 if(len
& (Vcb
->LBlockSize
-1)) {
411 Extent
[i
].extLength
= (len
+Vcb
->LBlockSize
-1) & ~(Vcb
->LBlockSize
-1);
412 locAddr
.logicalBlockNum
= AllocDesc
[i
].extPosition
;
413 // Note: for compatibility Adaptec DirectCD we check 'len' here
414 // That strange implementation records bogus extLocation in terminal entries
415 if(type
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
&& len
) {
416 Extent
[i
].extLocation
= UDFPartLbaToPhys(Vcb
, &locAddr
);
417 if(Extent
[i
].extLocation
== LBA_OUT_OF_EXTENT
) {
418 KdPrint(("bad address (2)\n"));
419 MyFreePool__(Extent
);
423 Extent
[i
].extLocation
= 0;
426 // some UDF implementations set strange AllocDesc sequence length,
427 // but terminates it with zeros in proper place, so handle
430 ASSERT(!Extent
[i
].extLength
);
431 Extent
[i
].extLocation
= 0;
432 if(/*!SubCallCount &&*/ w2k_compat
) {
433 ExtPrint(("w2k-compat\n"));
434 AllocLoc
->Flags
|= EXTENT_FLAG_2K_COMPAT
;
438 Extent
[i
].extLength
|= (type
<< 30);
441 Extent
[i
].extLength
= 0;
442 Extent
[i
].extLocation
= 0;
444 if(/*!SubCallCount &&*/ w2k_compat
) {
445 ExtPrint(("w2k-compat\n"));
446 AllocLoc
->Flags
|= EXTENT_FLAG_2K_COMPAT
;
450 } // end UDFShortAllocDescToMapping()
453 This routine builds file mapping according to LongAllocDesc (LONG_AD)
457 UDFLongAllocDescToMapping(
459 IN PLONG_AD AllocDesc
,
460 IN uint32 AllocDescLength
,
461 IN uint32 SubCallCount
,
462 OUT PEXTENT_INFO AllocLoc
// .Mapping must be intialized (non-Zero)
465 uint32 i
, lim
, l
, len
, type
;
467 PEXTENT_MAP Extent
, Extent2
, AllocMap
;
469 PALLOC_EXT_DESC NextAllocDesc
;
471 EXTENT_INFO NextAllocLoc
;
473 ExtPrint(("UDFLongAllocDescToMapping: len=%x\n", AllocDescLength
));
475 if(SubCallCount
> ALLOC_DESC_MAX_RECURSE
) return NULL
;
477 // BSh = Vcb->BlockSizeBits;
478 l
= ((lim
= (AllocDescLength
/sizeof(LONG_AD
))) + 1 ) * sizeof(EXTENT_AD
);
479 Extent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, l
, MEM_EXTMAP_TAG
);
480 if(!Extent
) return NULL
;
482 NextAllocLoc
.Offset
= 0;
485 type
= AllocDesc
[i
].extLength
>> 30;
486 len
= AllocDesc
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
487 ExtPrint(("LnExt: type %x, loc %x (%x:%x), len %x\n", type
, UDFPartLbaToPhys(Vcb
,&(AllocDesc
[i
].extLocation
)),
488 AllocDesc
[i
].extLocation
.partitionReferenceNum
, AllocDesc
[i
].extLocation
.logicalBlockNum
,
490 if(type
== EXTENT_NEXT_EXTENT_ALLOCDESC
) {
491 // read next frag of allocation descriptors if encountered
492 if(len
< sizeof(ALLOC_EXT_DESC
)) {
493 MyFreePool__(Extent
);
496 NextAllocDesc
= (PALLOC_EXT_DESC
)MyAllocatePoolTag__(NonPagedPool
, len
, MEM_ALLOCDESC_TAG
);
498 MyFreePool__(Extent
);
501 // record information about this frag
502 AllocExt
.extLength
= len
;
503 AllocExt
.extLocation
= UDFPartLbaToPhys(Vcb
,&(AllocDesc
[i
].extLocation
));
504 if(AllocExt
.extLocation
== LBA_OUT_OF_EXTENT
) {
505 KdPrint(("bad address\n"));
506 MyFreePool__(NextAllocDesc
);
507 MyFreePool__(Extent
);
510 NextAllocLoc
.Mapping
=
511 AllocMap
= UDFExtentToMapping(&AllocExt
);
512 NextAllocLoc
.Length
= len
;
514 MyFreePool__(NextAllocDesc
);
515 MyFreePool__(Extent
);
518 AllocLoc
->Mapping
= UDFMergeMappings(AllocLoc
->Mapping
, AllocMap
);
519 if(!AllocLoc
->Mapping
||
521 !OS_SUCCESS(UDFReadExtent(Vcb
, &NextAllocLoc
,
522 0, len
, FALSE
, (int8
*)NextAllocDesc
, &ReadBytes
)))
524 MyFreePool__(AllocMap
);
525 MyFreePool__(NextAllocDesc
);
526 MyFreePool__(Extent
);
529 MyFreePool__(AllocMap
);
531 if((NextAllocDesc
->descTag
.tagIdent
!= TID_ALLOC_EXTENT_DESC
) ||
532 (NextAllocDesc
->lengthAllocDescs
> (len
- sizeof(ALLOC_EXT_DESC
))) ) {
533 KdPrint(("Integrity check failed\n"));
534 KdPrint(("NextAllocDesc->descTag.tagIdent = %x\n", NextAllocDesc
->descTag
.tagIdent
));
535 KdPrint(("NextAllocDesc->lengthAllocDescs = %x\n", NextAllocDesc
->lengthAllocDescs
));
536 KdPrint(("len = %x\n", len
));
537 MyFreePool__(NextAllocDesc
);
538 MyFreePool__(Extent
);
541 // perform recursive call to obtain mapping
542 Extent2
= UDFLongAllocDescToMapping(Vcb
, (PLONG_AD
)(NextAllocDesc
+1),
543 NextAllocDesc
->lengthAllocDescs
, SubCallCount
+1, AllocLoc
);
545 MyFreePool__(NextAllocDesc
);
546 MyFreePool__(Extent
);
549 // and merge this 2 mappings into 1
550 Extent
[i
].extLength
= 0;
551 Extent
[i
].extLocation
= 0;
552 Extent
= UDFMergeMappings(Extent
, Extent2
);
553 MyFreePool__(Extent2
);
557 Extent
[i
].extLength
= len
;
558 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
559 ASSERT(!(len
& (Vcb
->LBlockSize
-1) ));
560 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
561 Extent
[i
].extLength
= (len
+Vcb
->LBlockSize
-1) & ~(Vcb
->LBlockSize
-1);
562 // Note: for compatibility Adaptec DirectCD we check 'len' here
563 // That strange implementation records bogus extLocation in terminal entries
564 if(type
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
&& len
) {
565 Extent
[i
].extLocation
= UDFPartLbaToPhys(Vcb
,&(AllocDesc
[i
].extLocation
));
566 if(Extent
[i
].extLocation
== LBA_OUT_OF_EXTENT
) {
567 KdPrint(("bad address (2)\n"));
568 MyFreePool__(Extent
);
572 Extent
[i
].extLocation
= 0;
575 // some UDF implementations set strange AllocDesc sequence length,
576 // but terminates it with zeros in proper place, so handle
578 Extent
[i
].extLocation
= 0;
581 Extent
[i
].extLength
|= (type
<< 30);
584 Extent
[i
].extLength
= 0;
585 Extent
[i
].extLocation
= 0;
588 } // end UDFLongAllocDescToMapping()
591 This routine builds file mapping according to ExtendedAllocDesc (EXT_AD)
595 UDFExtAllocDescToMapping(
597 IN PEXT_AD AllocDesc
,
598 IN uint32 AllocDescLength
,
599 IN uint32 SubCallCount
,
600 OUT PEXTENT_INFO AllocLoc
// .Mapping must be intialized (non-Zero)
603 uint32 i
, lim
, l
, len
, type
;
605 PEXTENT_MAP Extent
, Extent2
, AllocMap
;
607 PALLOC_EXT_DESC NextAllocDesc
;
609 EXTENT_INFO NextAllocLoc
;
611 ExtPrint(("UDFExtAllocDescToMapping: len=%x\n", AllocDescLength
));
613 if(SubCallCount
> ALLOC_DESC_MAX_RECURSE
) return NULL
;
615 // BSh = Vcb->BlockSizeBits;
616 l
= ((lim
= (AllocDescLength
/sizeof(EXT_AD
))) + 1 ) * sizeof(EXTENT_AD
);
617 Extent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, l
, MEM_EXTMAP_TAG
);
618 if(!Extent
) return NULL
;
620 NextAllocLoc
.Offset
= 0;
623 type
= AllocDesc
[i
].extLength
>> 30;
624 len
= AllocDesc
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
625 ExtPrint(("ExExt: type %x, loc %x, len %x\n", type
, UDFPartLbaToPhys(Vcb
,&(AllocDesc
[i
].extLocation
)), len
));
626 if(type
== EXTENT_NEXT_EXTENT_ALLOCDESC
) {
627 // read next frag of allocation descriptors if encountered
628 if(len
< sizeof(ALLOC_EXT_DESC
)) {
629 MyFreePool__(Extent
);
632 NextAllocDesc
= (PALLOC_EXT_DESC
)MyAllocatePoolTag__(NonPagedPool
, len
, MEM_ALLOCDESC_TAG
);
634 MyFreePool__(Extent
);
637 // record information about this frag
638 AllocExt
.extLength
= len
;
639 AllocExt
.extLocation
= UDFPartLbaToPhys(Vcb
,&(AllocDesc
[i
].extLocation
));
640 if(AllocExt
.extLocation
== LBA_OUT_OF_EXTENT
) {
641 KdPrint(("bad address\n"));
642 MyFreePool__(NextAllocDesc
);
643 MyFreePool__(Extent
);
646 NextAllocLoc
.Mapping
=
647 AllocMap
= UDFExtentToMapping(&AllocExt
);
648 NextAllocLoc
.Length
= len
;
650 MyFreePool__(NextAllocDesc
);
651 MyFreePool__(Extent
);
654 AllocLoc
->Mapping
= UDFMergeMappings(AllocLoc
->Mapping
, AllocMap
);
655 if(!AllocLoc
->Mapping
||
657 !OS_SUCCESS(UDFReadExtent(Vcb
, &NextAllocLoc
,
658 0, len
, FALSE
, (int8
*)NextAllocDesc
, &ReadBytes
)))
660 MyFreePool__(AllocMap
);
661 MyFreePool__(NextAllocDesc
);
662 MyFreePool__(Extent
);
665 MyFreePool__(AllocMap
);
667 if((NextAllocDesc
->descTag
.tagIdent
!= TID_ALLOC_EXTENT_DESC
) ||
668 (NextAllocDesc
->lengthAllocDescs
> (len
- sizeof(ALLOC_EXT_DESC
))) ) {
669 KdPrint(("Integrity check failed\n"));
670 MyFreePool__(NextAllocDesc
);
671 MyFreePool__(Extent
);
674 // perform recursive call to obtain mapping
675 Extent2
= UDFExtAllocDescToMapping(Vcb
, (PEXT_AD
)(NextAllocDesc
+1),
676 NextAllocDesc
->lengthAllocDescs
, SubCallCount
+1, AllocLoc
);
678 MyFreePool__(NextAllocDesc
);
679 MyFreePool__(Extent
);
682 // and merge this 2 mappings into 1
683 Extent
[i
].extLength
= 0;
684 Extent
[i
].extLocation
= 0;
685 Extent
= UDFMergeMappings(Extent
, Extent2
);
686 MyFreePool__(Extent2
);
689 /* if((AllocDesc[i].extLength & UDF_EXTENT_LENGTH_MASK) > // Uncomment!!!
690 (AllocDesc[i].recordedLength & UDF_EXTENT_LENGTH_MASK)) {
691 Extent[i].extLength = AllocDesc[i].recordedLength;
692 Extent[i].extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation));
694 Extent
[i
].extLength
= len
;
695 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT
696 ASSERT(!(len
& (Vcb
->LBlockSize
-1) ));
697 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT
698 // Note: for compatibility Adaptec DirectCD we check 'len' here
699 // That strange implementation records bogus extLocation in terminal entries
700 if(type
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
&& len
) {
701 Extent
[i
].extLocation
= UDFPartLbaToPhys(Vcb
,&(AllocDesc
[i
].extLocation
));
702 if(Extent
[i
].extLocation
== LBA_OUT_OF_EXTENT
) {
703 KdPrint(("bad address (2)\n"));
704 MyFreePool__(Extent
);
708 Extent
[i
].extLocation
= 0;
711 // some UDF implementations set strange AllocDesc sequence length,
712 // but terminates it with zeros in proper place, so handle
714 Extent
[i
].extLocation
= 0;
717 Extent
[i
].extLength
|= (type
<< 30);
720 Extent
[i
].extLength
= 0;
721 Extent
[i
].extLocation
= 0;
724 } // end UDFExtAllocDescToMapping()
728 This routine builds FileMapping according to given FileEntry
729 Return: pointer to EXTENT_MAP array
730 or offset inside FileEntry (negative)
731 when ICB_FLAG_AD_IN_ICB encountered
732 of NULL if an error occured
735 UDFReadMappingFromXEntry(
739 IN OUT uint32
* Offset
,
740 OUT PEXTENT_INFO AllocLoc
// .Mapping must be intialized (non-Zero)
747 // EntityID* eID; // for compatibility with Adaptec DirectCD
753 if(XEntry
->tagIdent
== TID_FILE_ENTRY
) {
754 // KdPrint(("Standard FileEntry\n"));
755 PFILE_ENTRY FileEntry
= (PFILE_ENTRY
)XEntry
;
756 ExtPrint(("Standard FileEntry\n"));
758 AllocDescs
= (int8
*)(((int8
*)(FileEntry
+1))+(FileEntry
->lengthExtendedAttr
));
759 len
= FileEntry
->lengthAllocDescs
;
760 AllocLoc
->Offset
= sizeof(FILE_ENTRY
) + FileEntry
->lengthExtendedAttr
;
761 // eID = &(FileEntry->impIdent);
763 AllocMode
= FileEntry
->icbTag
.flags
& ICB_FLAG_ALLOC_MASK
;
765 } else if(XEntry
->tagIdent
== TID_EXTENDED_FILE_ENTRY
) {
766 // KdPrint(("Extended FileEntry\n"));
767 ExtPrint(("Extended FileEntry\n"));
768 PEXTENDED_FILE_ENTRY ExFileEntry
= (PEXTENDED_FILE_ENTRY
)XEntry
;
770 AllocDescs
= (((int8
*)(ExFileEntry
+1))+(ExFileEntry
->lengthExtendedAttr
));
771 len
= ExFileEntry
->lengthAllocDescs
;
772 AllocLoc
->Offset
= sizeof(EXTENDED_FILE_ENTRY
) + ExFileEntry
->lengthExtendedAttr
;
773 // eID = &(FileEntry->impIdent);
775 AllocMode
= ExFileEntry
->icbTag
.flags
& ICB_FLAG_ALLOC_MASK
;
781 // for compatibility with Adaptec DirectCD
782 // if(!(Vcb->UDF_VCB_IC_ADAPTEC_NONALLOC_COMPAT))
784 AllocLoc
->Length
=len
;
785 AllocLoc
->Flags
|= EXTENT_FLAG_VERIFY
; // for metadata
788 case ICB_FLAG_AD_SHORT
: {
789 Extent
= UDFShortAllocDescToMapping(Vcb
, PartNum
, (PSHORT_AD
)AllocDescs
, len
, 0, AllocLoc
);
792 case ICB_FLAG_AD_LONG
: {
793 Extent
= UDFLongAllocDescToMapping(Vcb
, (PLONG_AD
)AllocDescs
, len
, 0, AllocLoc
);
796 case ICB_FLAG_AD_EXTENDED
: {
797 Extent
= UDFExtAllocDescToMapping(Vcb
, (PEXT_AD
)AllocDescs
, len
, 0, AllocLoc
);
800 default : { // case ICB_FLAG_AD_IN_ICB
802 *Offset
= (uint32
)AllocDescs
- (uint32
)XEntry
;
805 if(AllocLoc
->Mapping
) MyFreePool__(AllocLoc
->Mapping
);
806 AllocLoc
->Mapping
=NULL
;
811 ExtPrint(("UDFReadMappingFromXEntry: mode %x, loc %x, len %x\n", AllocMode
,
812 AllocLoc
->Mapping
? AllocLoc
->Mapping
[0].extLocation
: -1, len
));
814 UDFCheckSpaceAllocation(Vcb
, 0, Extent
, AS_USED
); // check if used
817 }// end UDFReadMappingFromXEntry()
819 #ifndef UDF_READ_ONLY_BUILD
821 This routine builds data for AllocDesc sequence for specified
825 UDFBuildShortAllocDescs(
828 OUT int8
** Buff
, // data for AllocLoc
830 IN OUT PUDF_FILE_INFO FileInfo
835 PEXTENT_MAP Extent
= FileInfo
->Dloc
->DataLoc
.Mapping
;
836 PEXTENT_INFO AllocExtent
= &(FileInfo
->Dloc
->AllocLoc
);
840 uint32 ph_len
=0; // in general, this should be uint64,
841 // but we need its lower part only
842 #ifdef UDF_ALLOW_FRAG_AD
844 uint32 LBS
= Vcb
->LBlockSize
;
845 uint32 LBSh
= Vcb
->BlockSizeBits
;
848 PSHORT_AD saved_Alloc
;
849 uint32 TagLoc
, prevTagLoc
;
853 #endif //UDF_ALLOW_FRAG_AD
855 ValidateFileInfo(FileInfo
);
856 ExtPrint(("UDFBuildShortAllocDescs: FE %x\n", FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
));
858 for(len
=0; (i
=(Extent
[len
].extLength
& UDF_EXTENT_LENGTH_MASK
)); len
++, ph_len
+=i
) {
859 ExtPrint(("bShExt: type %x, loc %x, len %x\n",
860 Extent
[len
].extLength
>> 30, Extent
[len
].extLocation
, Extent
[len
].extLength
& UDF_EXTENT_LENGTH_MASK
));
862 Alloc
= (PSHORT_AD
)MyAllocatePoolTag__(NonPagedPool
, (len
+1)*sizeof(SHORT_AD
), MEM_SHAD_TAG
);
865 return STATUS_INSUFFICIENT_RESOURCES
;
867 // fill contiguous AllocDesc buffer (decribing UserData)
869 Alloc
[i
].extLength
= Extent
[i
].extLength
;
870 Alloc
[i
].extPosition
= UDFPhysLbaToPart(Vcb
, PartNum
, Extent
[i
].extLocation
);
872 if((Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
) && i
) {
873 Alloc
[i
-1].extLength
-= (ph_len
- (ULONG
)(FileInfo
->Dloc
->DataLoc
.Length
)) &
875 ExtPrint(("bShExt: cut tail -> %x\n",
876 Alloc
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
));
879 Alloc
[i
].extPosition
= 0;
880 j
= len
*sizeof(SHORT_AD
); // required space
881 len
= (InitSz
& ~(sizeof(SHORT_AD
)-1)); // space available in 1st block
882 ASSERT(len
== InitSz
);
884 // Ok. Let's init AllocLoc
885 if(!(FileInfo
->Dloc
->AllocLoc
.Mapping
)) {
886 FileInfo
->Dloc
->AllocLoc
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, 2 * sizeof(EXTENT_MAP
), MEM_EXTMAP_TAG
);
887 if(!(FileInfo
->Dloc
->AllocLoc
.Mapping
)) {
890 return STATUS_INSUFFICIENT_RESOURCES
;
892 // allocation descriptors are located in the same sector as FileEntry
893 // (at least their 1st part), just after it
894 FileInfo
->Dloc
->AllocLoc
.Mapping
[0] = FileInfo
->Dloc
->FELoc
.Mapping
[0];
895 FileInfo
->Dloc
->AllocLoc
.Offset
= FileInfo
->Dloc
->FileEntryLen
;
896 FileInfo
->Dloc
->AllocLoc
.Length
= 0;
898 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLength
=
899 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLocation
= 0;
903 // we needn't allocating additional blocks to store AllocDescs
904 AdPrint(("in-ICB AllocDescs, j=%x\n",j
));
905 RtlCopyMemory(*Buff
, (int8
*)Alloc
, j
);
909 #ifndef UDF_ALLOW_FRAG_AD
910 AdPrint((" DISK_FULL\n"));
911 return STATUS_DISK_FULL
;
912 #else //UDF_ALLOW_FRAG_AD
913 AdPrint(("multi-block AllocDescs, j=%x\n",j
));
915 TagLoc
= prevTagLoc
= 0;
916 // calculate the space available for SHORT_ADs in each block
917 ac
= (LBS
- (sizeof(ALLOC_EXT_DESC
) + sizeof(SHORT_AD
))) & ~(sizeof(SHORT_AD
)-1);
921 len
-= sizeof(SHORT_AD
);
922 // calculate actual AllocSequence length (in bytes)
923 NewLen
= ( ((j
- len
+ ac
- 1) / ac
) << LBSh
) + InitSz
+ sizeof(SHORT_AD
);
925 (*Buff
) = (int8
*)MyAllocatePoolTag__(NonPagedPool
, NewLen
, MEM_SHAD_TAG
);
927 status
= STATUS_INSUFFICIENT_RESOURCES
;
928 KdPrint(("UDFResizeExtent() failed (%x)\n",status
));
932 if(UDFGetExtentLength(AllocExtent
->Mapping
) < NewLen
) {
933 status
= UDFResizeExtent(Vcb
, PartNum
, NewLen
, TRUE
, AllocExtent
);
934 if(!OS_SUCCESS(status
)) {
935 KdPrint(("UDFResizeExtent(2) failed (%x)\n",status
));
942 ExtOffs
= AllocExtent
->Offset
;
943 RtlZeroMemory(*Buff
, NewLen
);
944 saved_NewLen
= NewLen
;
945 NewLen
= 0; // recorded length
947 // fill buffer sector by sector (adding links at the end of each one)
950 // j - remained AllocDescs length (in bytes)
951 // len - bytes available for AllocDescs in current block
952 // ac - bytes available for AllocDescs in each block
954 // leave space for terminator or pointer to next part of sequence
956 // if we have only 1 SHORT_AD that we can fit in last sector
957 // we shall do it instead of recording link & allocating new block
961 ASSERT(saved_NewLen
>= (BufOffs
+ len
));
962 RtlCopyMemory( (*Buff
)+BufOffs
, (int8
*)Alloc
, len
);
963 Alloc
= (PSHORT_AD
)((int8
*)Alloc
+ len
);
967 // Set up Tag for AllocDesc
968 Tag
->tagIdent
= TID_ALLOC_EXTENT_DESC
;
969 UDFSetUpTag(Vcb
, Tag
, (uint16
)TagLen
, TagLoc
);
978 if(j
<= (len
+ sizeof(SHORT_AD
)))
979 len
= j
- sizeof(SHORT_AD
);
980 len2
= len
+ sizeof(SHORT_AD
);
981 // we have more than 1 SHORT_AD that we can't fit in current block
982 // so we shall set up pointer to the next block
983 ((PSHORT_AD
)((*Buff
)+BufOffs
))->extLength
= /*LBS*/ len2
|
984 (((uint32
)EXTENT_NEXT_EXTENT_ALLOCDESC
) << 30) ;
985 ((PSHORT_AD
)((*Buff
)+BufOffs
))->extPosition
= TagLoc
=
986 UDFPhysLbaToPart(Vcb
, PartNum
,
987 UDFExtentOffsetToLba(Vcb
, AllocExtent
->Mapping
,
988 ExtOffs
+BufOffs
+sizeof(SHORT_AD
)+ts
,
989 NULL
, NULL
, NULL
, NULL
) );
990 // reflect additional (link) block & LBlock tail (if any)
991 BufOffs
+= ts
+sizeof(SHORT_AD
);
993 ( (PALLOC_EXT_DESC
) ((*Buff
)+BufOffs
))->lengthAllocDescs
= len2
;
994 ( (PALLOC_EXT_DESC
) ((*Buff
)+BufOffs
))->previousAllocExtLocation
= prevTagLoc
;
995 Tag
= (tag
*)((*Buff
)+BufOffs
);
997 ts
= LBS
-len2
-sizeof(ALLOC_EXT_DESC
);
998 BufOffs
+= sizeof(ALLOC_EXT_DESC
);
1000 MyFreePool__(saved_Alloc
);
1001 #endif //UDF_ALLOW_FRAG_AD
1003 status
= UDFResizeExtent(Vcb
, PartNum
, NewLen
, TRUE
, AllocExtent
);
1005 } // end UDFBuildShortAllocDescs()
1008 This routine builds data for AllocDesc sequence for specified
1012 UDFBuildLongAllocDescs(
1015 OUT int8
** Buff
, // data for AllocLoc
1017 IN OUT PUDF_FILE_INFO FileInfo
1022 PEXTENT_MAP Extent
= FileInfo
->Dloc
->DataLoc
.Mapping
;
1023 PEXTENT_INFO AllocExtent
= &(FileInfo
->Dloc
->AllocLoc
);
1027 uint32 ph_len
=0; // in general, this should be uint64,
1028 // but we need its lower part only
1029 #ifdef UDF_ALLOW_FRAG_AD
1030 uint32 ac
, len2
, ts
;
1031 uint32 TagLoc
, prevTagLoc
;
1032 uint32 LBS
= Vcb
->LBlockSize
;
1033 uint32 LBSh
= Vcb
->BlockSizeBits
;
1035 uint32 ExtOffs
= AllocExtent
->Offset
;
1036 PLONG_AD saved_Alloc
;
1039 #endif //UDF_ALLOW_FRAG_AD
1041 ValidateFileInfo(FileInfo
);
1042 ExtPrint(("UDFBuildLongAllocDescs: FE %x\n", FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
));
1044 //for(len=0; i=(Extent[len].extLength & UDF_EXTENT_LENGTH_MASK); len++, ph_len+=i);
1045 for(len
=0; (i
=(Extent
[len
].extLength
& UDF_EXTENT_LENGTH_MASK
)); len
++, ph_len
+=i
) {
1046 ExtPrint(("bLnExt: type %x, loc %x, len %x\n",
1047 Extent
[len
].extLength
>> 30, Extent
[len
].extLocation
, Extent
[len
].extLength
& UDF_EXTENT_LENGTH_MASK
));
1049 Alloc
= (PLONG_AD
)MyAllocatePoolTag__(NonPagedPool
, (len
+1)*sizeof(LONG_AD
), MEM_LNGAD_TAG
);
1050 if(!Alloc
) return STATUS_INSUFFICIENT_RESOURCES
;
1051 // fill contiguous AllocDesc buffer (decribing UserData)
1052 for(i
=0;i
<len
;i
++) {
1053 Alloc
[i
].extLength
= Extent
[i
].extLength
;
1054 Alloc
[i
].extLocation
.logicalBlockNum
= UDFPhysLbaToPart(Vcb
, PartNum
, Extent
[i
].extLocation
);
1055 Alloc
[i
].extLocation
.partitionReferenceNum
= (uint16
)PartNum
;
1056 RtlZeroMemory(&(Alloc
[i
].impUse
), sizeof(Alloc
[i
].impUse
));
1058 if((Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
) && i
) {
1059 Alloc
[i
-1].extLength
-= (ph_len
- (ULONG
)(FileInfo
->Dloc
->DataLoc
.Length
)) &
1060 (Vcb
->LBlockSize
-1);
1061 ExtPrint(("bLnExt: cut tail -> %x\n",
1062 Alloc
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
));
1064 RtlZeroMemory(&(Alloc
[i
]), sizeof(LONG_AD
));
1065 j
= len
*sizeof(LONG_AD
); // required space
1066 len
= (InitSz
& ~(sizeof(LONG_AD
)-1)); // space available in 1st block
1067 ASSERT(len
== InitSz
);
1069 // Ok. Let's init AllocLoc
1070 if(!(FileInfo
->Dloc
->AllocLoc
.Mapping
)) {
1071 FileInfo
->Dloc
->AllocLoc
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, 2 * sizeof(EXTENT_MAP
), MEM_EXTMAP_TAG
);
1072 if(!(FileInfo
->Dloc
->AllocLoc
.Mapping
)) {
1073 MyFreePool__(Alloc
);
1074 return STATUS_INSUFFICIENT_RESOURCES
;
1076 // allocation descriptors are located in the same sector as FileEntry
1077 // (at least their 1st part), just after it
1078 FileInfo
->Dloc
->AllocLoc
.Mapping
[0] = FileInfo
->Dloc
->FELoc
.Mapping
[0];
1079 FileInfo
->Dloc
->AllocLoc
.Offset
= FileInfo
->Dloc
->FileEntryLen
;
1080 FileInfo
->Dloc
->AllocLoc
.Length
= 0;
1082 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLength
=
1083 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLocation
= 0;
1087 // we needn't allocating additional blocks to store AllocDescs
1088 RtlCopyMemory(*Buff
, (int8
*)Alloc
, j
);
1090 MyFreePool__(Alloc
);
1092 #ifndef UDF_ALLOW_FRAG_AD
1093 AdPrint((" DISK_FULL\n"));
1094 return STATUS_DISK_FULL
;
1095 #else //UDF_ALLOW_FRAG_AD
1097 TagLoc
= prevTagLoc
= 0;
1098 // calculate the space available for LONG_ADs in each block
1099 ac
= (LBS
- (sizeof(ALLOC_EXT_DESC
) + sizeof(LONG_AD
))) & ~(sizeof(LONG_AD
)-1);
1103 len
-= sizeof(LONG_AD
);
1104 // calculate actual AllocSequence length (in LBlocks)
1105 NewLen
= ( ((j
- len
+ ac
- 1) / ac
) << LBSh
) + InitSz
+ sizeof(LONG_AD
);
1106 MyFreePool__(*Buff
);
1107 (*Buff
) = (int8
*)MyAllocatePoolTag__(NonPagedPool
, NewLen
, MEM_LNGAD_TAG
);
1109 status
= STATUS_INSUFFICIENT_RESOURCES
;
1112 if(UDFGetExtentLength(AllocExtent
->Mapping
) < NewLen
) {
1113 status
= UDFResizeExtent(Vcb
, PartNum
, NewLen
, TRUE
, AllocExtent
);
1114 if(!OS_SUCCESS(status
)) {
1116 MyFreePool__(Alloc
);
1120 ExtOffs
= AllocExtent
->Offset
;
1121 RtlZeroMemory(*Buff
, NewLen
);
1122 NewLen
= 0; // recorded length
1123 saved_Alloc
= Alloc
;
1124 len2
= len
+sizeof(LONG_AD
);
1125 // fill buffer sector by sector (adding links at the end of each one)
1128 // j - remained AllocDescs length (in bytes)
1129 // len - bytes available for in AllocDescs each block
1131 // leave space for terminator or pointer to next part of sequence
1133 // if we have only 1 LONG_AD that we can fit in last sector
1134 // we shall do it instead of recording link & allocating new block
1138 RtlCopyMemory( (*Buff
)+BufOffs
, (int8
*)Alloc
, len
);
1139 Alloc
= (PLONG_AD
)((int8
*)Alloc
+ len
);
1143 // Set up Tag for AllocDesc
1144 Tag
->tagIdent
= TID_ALLOC_EXTENT_DESC
;
1145 UDFSetUpTag(Vcb
, Tag
, (uint16
)TagLen
, TagLoc
);
1146 prevTagLoc
= TagLoc
;
1154 if(j
<= (len
+ sizeof(LONG_AD
)))
1155 len
= j
- sizeof(LONG_AD
);
1156 len2
= len
+sizeof(LONG_AD
);
1157 // we have more than 1 LONG_AD that we can't fit in current block
1158 // so we shall set up pointer to the next block
1159 ((PLONG_AD
)((*Buff
)+BufOffs
))->extLength
= /*LBS*/ len2
|
1160 (((uint32
)EXTENT_NEXT_EXTENT_ALLOCDESC
) << 30) ;
1161 ((PLONG_AD
)((*Buff
)+BufOffs
))->extLocation
.logicalBlockNum
= TagLoc
=
1162 UDFPhysLbaToPart(Vcb
, PartNum
,
1163 UDFExtentOffsetToLba(Vcb
, AllocExtent
->Mapping
,
1164 ExtOffs
+BufOffs
+sizeof(LONG_AD
)+ts
,
1165 NULL
, NULL
, NULL
, NULL
) );
1166 ((PLONG_AD
)((*Buff
)+BufOffs
))->extLocation
.partitionReferenceNum
= (uint16
)PartNum
;
1167 // reflect additional (link) block & LBlock tail (if any)
1168 BufOffs
+= ts
+sizeof(LONG_AD
);
1170 ( (PALLOC_EXT_DESC
) ((*Buff
)+BufOffs
))->lengthAllocDescs
= len2
;
1171 ( (PALLOC_EXT_DESC
) ((*Buff
)+BufOffs
))->previousAllocExtLocation
= prevTagLoc
;
1172 Tag
= (tag
*)((*Buff
)+BufOffs
);
1174 ts
= LBS
-len2
-sizeof(ALLOC_EXT_DESC
);
1175 BufOffs
+= sizeof(ALLOC_EXT_DESC
);
1177 MyFreePool__(saved_Alloc
);
1178 #endif //UDF_ALLOW_FRAG_AD
1180 status
= UDFResizeExtent(Vcb
, PartNum
, NewLen
, TRUE
, AllocExtent
);
1182 } // end UDFBuildLongAllocDescs()
1185 This routine builds data for AllocDesc sequence for specified
1189 UDFBuildExtAllocDescs(
1192 OUT int8** Buff, // data for AllocLoc
1194 IN OUT PUDF_FILE_INFO FileInfo
1198 uint32 len=0, ac, len2;
1199 uint32 TagLoc, prevTagLoc;
1200 uint32 LBS = Vcb->LBlockSize;
1201 uint32 LBSh = Vcb->BlockSizeBits;
1202 PEXTENT_MAP Extent = FileInfo->Dloc->DataLoc.Mapping;
1203 PEXTENT_INFO AllocExtent = &(FileInfo->Dloc->AllocLoc);
1204 PEXT_AD Alloc, saved_Alloc;
1206 uint32 ExtOffs = AllocExtent->Offset;
1212 ValidateFileInfo(FileInfo);
1214 for(len=0; Extent[len].extLength; len++);
1215 Alloc = (PEXT_AD)MyAllocatePool__(NonPagedPool, (len+1)*sizeof(EXT_AD));
1216 if(!Alloc) return STATUS_INSUFFICIENT_RESOURCES;
1217 // fill contiguous AllocDesc buffer (decribing UserData)
1218 for(i=0;i<len;i++) {
1219 Alloc[i].extLength =
1220 Alloc[i].recordedLength =
1221 Alloc[i].informationLength = Extent[i].extLength;
1222 Alloc[i].extLocation.logicalBlockNum = UDFPhysLbaToPart(Vcb, PartNum, Extent[i].extLocation);
1223 Alloc[i].extLocation.partitionReferenceNum = (uint16)PartNum;
1225 RtlZeroMemory(&(Alloc[i]), sizeof(EXT_AD));
1226 j = len*sizeof(EXT_AD); // required space
1227 len = InitSz; // space available in 1st block
1229 // Ok. Let's init AllocLoc
1230 if(!(FileInfo->Dloc->AllocLoc.Mapping)) {
1231 FileInfo->Dloc->AllocLoc.Mapping = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, 2 * sizeof(EXTENT_MAP));
1232 if(!(FileInfo->Dloc->AllocLoc.Mapping)) {
1233 MyFreePool__(Alloc);
1234 return STATUS_INSUFFICIENT_RESOURCES;
1236 // allocation descriptors are located in the same sector as FileEntry
1237 // (at least their 1st part), just after it
1238 FileInfo->Dloc->AllocLoc.Mapping[0] = FileInfo->Dloc->FELoc.Mapping[0];
1239 FileInfo->Dloc->AllocLoc.Offset = FileInfo->Dloc->FileEntryLen;
1240 FileInfo->Dloc->AllocLoc.Length = 0;
1242 FileInfo->Dloc->AllocLoc.Mapping[1].extLength =
1243 FileInfo->Dloc->AllocLoc.Mapping[1].extLocation = 0;
1247 // we needn't allocating additional blocks to store AllocDescs
1248 RtlCopyMemory(*Buff, (int8*)Alloc, j);
1250 MyFreePool__(Alloc);
1253 TagLoc = prevTagLoc = 0;
1254 // calculate the space available for EXT_ADs in each block
1255 ac = (LBS - (sizeof(ALLOC_EXT_DESC) + sizeof(EXT_AD))) & ~(sizeof(EXT_AD)-1);
1256 // calculate actual AllocSequence length (in LBlocks)
1257 len -= sizeof(EXT_AD);
1258 NewLen = ( ((j - len + ac - 1) / ac) << LBSh) + len + sizeof(EXT_AD);
1259 MyFreePool__(*Buff);
1260 (*Buff) = (int8*)MyAllocatePool__(NonPagedPool, NewLen);
1261 if(UDFGetExtentLength(AllocExtent->Mapping) < NewLen) {
1262 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent);
1263 if(!OS_SUCCESS(status)) {
1264 MyFreePool__(Alloc);
1268 RtlZeroMemory(*Buff, NewLen);
1269 NewLen = 0; // recorded length
1270 saved_Alloc = Alloc;
1271 len2 = len + sizeof(EXT_AD);
1272 // fill buffer sector by sector (adding links at the end of each one)
1275 // j - remained AllocDescs length (in bytes)
1276 // len - bytes available for in AllocDescs each block
1278 // leave space for terminator or pointer to next part of sequence
1280 // if we have only 1 EXT_AD that we can fit in last sector
1281 // we shall do it instead of recording link & allocating new block
1285 RtlCopyMemory( (*Buff)+BufOffs, (int8*)Alloc, len);
1286 Alloc = (PEXT_AD)((int8*)Alloc + len);
1290 // Set up Tag for AllocDesc
1291 Tag->tagIdent = TID_ALLOC_EXTENT_DESC;
1292 UDFSetUpTag(Vcb, Tag, (uint16)TagLen, TagLoc);
1293 prevTagLoc = TagLoc;
1301 if(j <= (len + sizeof(EXT_AD)))
1302 len = j - sizeof(EXT_AD);
1303 len2 = len + sizeof(EXT_AD);
1304 // we have more than 1 EXT_AD that we can't fit in current block
1305 // so we shall set up pointer to the next block
1306 ((PEXT_AD)((*Buff)+BufOffs))->extLength =
1307 ((PEXT_AD)((*Buff)+BufOffs))->recordedLength = LBS;
1308 ((PEXT_AD)((*Buff)+BufOffs))->informationLength = len2 |
1309 (((uint32)EXTENT_NEXT_EXTENT_ALLOCDESC) << 30) ;
1310 ((PEXT_AD)((*Buff)+BufOffs))->extLocation.logicalBlockNum = TagLoc =
1311 UDFPhysLbaToPart(Vcb, PartNum,
1312 UDFExtentOffsetToLba(Vcb, AllocExtent->Mapping, ExtOffs + BufOffs + 2*sizeof(EXT_AD)-1, NULL, NULL, NULL, NULL) );
1313 ((PEXT_AD)((*Buff)+BufOffs))->extLocation.partitionReferenceNum = (uint16)PartNum;
1314 BufOffs = (BufOffs + 2*sizeof(EXT_AD) - 1) & ~(sizeof(EXT_AD)-1) ;
1316 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->lengthAllocDescs = len2;
1317 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->previousAllocExtLocation = prevTagLoc;
1318 Tag = (tag*)((*Buff)+BufOffs);
1320 BufOffs += sizeof(ALLOC_EXT_DESC);
1322 MyFreePool__(saved_Alloc);
1324 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent);
1326 } // end UDFBuildExtAllocDescs()*/
1331 IN PEXTENT_MAP Mapping
,
1335 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE
1336 PEXTENT_MAP Mapping2
;
1339 KdPrint((" DiscardFESpace\n"));
1341 for(i
=0;i
<lim
;i
++, Mapping
++) {
1342 // we should not discard allocated FEs
1343 if( (Mapping
->extLength
>> 30) == EXTENT_RECORDED_ALLOCATED
) {
1344 KdPrint((" used @ %x\n", Mapping
->extLocation
));
1345 Mapping
->extLength
= Vcb
->LBlockSize
| (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
1346 Mapping
->extLocation
= 0;
1348 KdPrint((" free @ %x\n", Mapping
->extLocation
));
1351 UDFMarkSpaceAsXXX(Vcb
, 0, Mapping2
, AS_DISCARDED
);
1353 MyFreePool__(Mapping2
);
1354 #else // UDF_FE_ALLOCATION_CHARGE
1355 ASSERT(!Dloc
->DirIndex
->FECharge
.Mapping
);
1357 #endif // UDF_FE_ALLOCATION_CHARGE
1358 } // end UDFDiscardFESpace()
1361 UDFInitAllocationCache(
1363 IN uint32 AllocClass
,
1364 OUT PUDF_ALLOCATION_CACHE_ITEM
* _AllocCache
,
1369 PUDF_ALLOCATION_CACHE_ITEM AllocCache
;
1370 PUDF_ALLOCATION_CACHE_ITEM
* pAllocCache
;
1374 switch(AllocClass
) {
1375 case UDF_PREALLOC_CLASS_FE
:
1376 KdPrint(("AllocationCache FE:\n"));
1377 pAllocCache
= &(Vcb
->FEChargeCache
);
1378 plim
= &(Vcb
->FEChargeCacheMaxSize
);
1381 case UDF_PREALLOC_CLASS_DIR
:
1382 KdPrint(("AllocationCache DIR:\n"));
1383 pAllocCache
= &(Vcb
->PreallocCache
);
1384 plim
= &(Vcb
->PreallocCacheMaxSize
);
1388 return STATUS_INVALID_PARAMETER
;
1392 return STATUS_UNSUCCESSFUL
;
1394 (*pAllocCache
) = AllocCache
=
1395 (PUDF_ALLOCATION_CACHE_ITEM
)
1396 MyAllocatePoolTag__(NonPagedPool
, sizeof(UDF_ALLOCATION_CACHE_ITEM
)*lim
,
1397 MEM_ALLOC_CACHE_TAG
);
1399 return STATUS_INSUFFICIENT_RESOURCES
;
1401 RtlZeroMemory(AllocCache
, sizeof(UDF_ALLOCATION_CACHE_ITEM
)*lim
);
1402 for(i
=0; i
<lim
; i
++) {
1403 AllocCache
[i
].ParentLocation
= LBA_NOT_ALLOCATED
;
1408 AllocCache
= (*pAllocCache
);
1411 (*_AllocCache
) = AllocCache
;
1413 return STATUS_SUCCESS
;
1414 } // end UDFInitAllocationCache()
1417 UDFGetCachedAllocation(
1419 IN uint32 ParentLocation
,
1420 OUT PEXTENT_INFO Ext
,
1421 OUT uint32
* Items
, // optional
1422 IN uint32 AllocClass
1425 PUDF_ALLOCATION_CACHE_ITEM AllocCache
;
1429 UDFAcquireResourceExclusive(&(Vcb
->PreallocResource
),TRUE
);
1431 status
= UDFInitAllocationCache(Vcb
, AllocClass
, &AllocCache
, &lim
, FALSE
);
1432 if(!OS_SUCCESS(status
)) {
1433 UDFReleaseResource(&(Vcb
->PreallocResource
));
1436 KdPrint(("Get AllocationCache for %x\n", ParentLocation
));
1438 for(i
=0; i
<lim
; i
++) {
1439 if(AllocCache
[i
].ParentLocation
== ParentLocation
) {
1440 (*Ext
) = AllocCache
[i
].Ext
;
1441 AdPrint((" map %x (%x)\n", Ext
->Mapping
, i
));
1443 (*Items
) = AllocCache
[i
].Items
;
1445 RtlZeroMemory(&(AllocCache
[i
]), sizeof(AllocCache
[i
]));
1446 AllocCache
[i
].ParentLocation
= LBA_NOT_ALLOCATED
;
1447 UDFReleaseResource(&(Vcb
->PreallocResource
));
1448 return STATUS_SUCCESS
;
1451 AdPrint((" no map\n"));
1452 UDFReleaseResource(&(Vcb
->PreallocResource
));
1453 return STATUS_UNSUCCESSFUL
;
1454 } // end UDFGetCachedAllocation()
1457 UDFStoreCachedAllocation(
1459 IN uint32 ParentLocation
,
1460 IN PEXTENT_INFO Ext
,
1462 IN uint32 AllocClass
1465 PUDF_ALLOCATION_CACHE_ITEM AllocCache
;
1469 UDFAcquireResourceExclusive(&(Vcb
->PreallocResource
),TRUE
);
1471 status
= UDFInitAllocationCache(Vcb
, AllocClass
, &AllocCache
, &lim
, TRUE
);
1472 if(!OS_SUCCESS(status
)) {
1473 UDFReleaseResource(&(Vcb
->PreallocResource
));
1476 KdPrint(("Store AllocationCache for %x, map %x\n", ParentLocation
, Ext
->Mapping
));
1478 for(i
=0; i
<lim
; i
++) {
1479 if(AllocCache
[i
].ParentLocation
== LBA_NOT_ALLOCATED
) {
1480 AdPrint((" stored in %x\n", i
));
1481 AllocCache
[i
].Ext
= (*Ext
);
1482 AllocCache
[i
].Items
= Items
;
1483 AllocCache
[i
].ParentLocation
= ParentLocation
;
1484 UDFReleaseResource(&(Vcb
->PreallocResource
));
1485 return STATUS_SUCCESS
;
1489 AdPrint((" drop map %x (%x)\n", AllocCache
[lim
-1].Ext
.Mapping
, lim
-1));
1490 switch(AllocClass
) {
1491 case UDF_PREALLOC_CLASS_FE
:
1492 UDFDiscardFESpace(Vcb
, AllocCache
[lim
-1].Ext
.Mapping
, AllocCache
[lim
-1].Items
);
1494 case UDF_PREALLOC_CLASS_DIR
:
1495 UDFMarkSpaceAsXXX(Vcb
, 0, AllocCache
[lim
-1].Ext
.Mapping
, AS_DISCARDED
);
1498 RtlMoveMemory(&(AllocCache
[1]), &(AllocCache
[0]), sizeof(UDF_ALLOCATION_CACHE_ITEM
)*(lim
-1));
1499 AllocCache
[0].Ext
= (*Ext
);
1500 AllocCache
[0].Items
= Items
;
1501 AllocCache
[0].ParentLocation
= ParentLocation
;
1502 AdPrint((" stored in 0\n"));
1503 UDFReleaseResource(&(Vcb
->PreallocResource
));
1504 return STATUS_SUCCESS
;
1505 } // end UDFStoreCachedAllocation()
1508 UDFFlushAllCachedAllocations(
1510 IN uint32 AllocClass
1513 PUDF_ALLOCATION_CACHE_ITEM AllocCache
;
1517 KdPrint(("Flush AllocationCache\n"));
1518 UDFAcquireResourceExclusive(&(Vcb
->PreallocResource
),TRUE
);
1520 status
= UDFInitAllocationCache(Vcb
, AllocClass
, &AllocCache
, &lim
, FALSE
);
1521 if(!OS_SUCCESS(status
)) {
1522 UDFReleaseResource(&(Vcb
->PreallocResource
));
1526 for(i
=0; i
<lim
; i
++) {
1527 if(AllocCache
[i
].ParentLocation
!= LBA_NOT_ALLOCATED
) {
1528 switch(AllocClass
) {
1529 case UDF_PREALLOC_CLASS_FE
:
1530 UDFDiscardFESpace(Vcb
, AllocCache
[i
].Ext
.Mapping
, AllocCache
[i
].Items
);
1532 case UDF_PREALLOC_CLASS_DIR
:
1533 UDFMarkSpaceAsXXX(Vcb
, 0, AllocCache
[i
].Ext
.Mapping
, AS_DISCARDED
);
1538 MyFreePool__(AllocCache
);
1539 switch(AllocClass
) {
1540 case UDF_PREALLOC_CLASS_FE
:
1541 Vcb
->FEChargeCache
= NULL
;
1542 Vcb
->FEChargeCacheMaxSize
= 0;
1544 case UDF_PREALLOC_CLASS_DIR
:
1545 Vcb
->PreallocCache
= NULL
;
1546 Vcb
->PreallocCacheMaxSize
= 0;
1549 UDFReleaseResource(&(Vcb
->PreallocResource
));
1551 return STATUS_SUCCESS
;
1552 } // end UDFFlushAllCachedAllocations()
1555 This routine allocates space for FE of the file being created
1556 If FE-Charge is enabled it reserves an extent & allocates
1557 space in it. It works much faster then usual way both while
1558 allocating & accessing on disk
1559 If FE-Charge is disabled FE may be allocated at any suitable
1565 IN PUDF_FILE_INFO DirInfo
,
1567 IN PEXTENT_INFO FEExtInfo
,
1571 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE
1575 BOOLEAN retry
= FALSE
;
1579 1. #Dir1#->*File* -> Dir1's FECharge
1580 2. #Dir1#->*Dir* -> Dir1's FECharge
1581 3. #Dir1#->*SDir* -> Dir1's FECharge
1582 4. Dir1->#SDir#->*Stream* -> Dir1's FEChargeSDir
1583 5. Dir1->#File#->*SDir* -> Dir1's FEChargeSDir
1584 6. Dir1->#Dir#->*SDir* -> (see p.2)
1585 7. Dir1->File->#SDir#->*Stream* -> Dir1's FEChargeSDir
1586 8. Dir1->Dir->#SDir#->*Stream* -> (see p.4)
1589 ** ~ Object to be created
1593 // ASSERT(!FEExtInfo->Mapping);
1594 // check if DirInfo we are called with is a Directory
1595 // (it can be a file with SDir)
1596 if(!DirInfo
|| !DirInfo
->Dloc
->DirIndex
||
1597 ((lim
= ((DirInfo
->Dloc
->FE_Flags
& UDF_FE_FLAG_IS_SDIR
) ? Vcb
->FEChargeSDir
: Vcb
->FECharge
)) <= 1))
1598 #endif // UDF_FE_ALLOCATION_CHARGE
1599 return UDFAllocFreeExtent(Vcb
, Len
,
1600 UDFPartStart(Vcb
, PartNum
), UDFPartEnd(Vcb
, PartNum
), FEExtInfo
, EXTENT_FLAG_VERIFY
);
1601 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE
1603 Ext
= &(DirInfo
->Dloc
->DirIndex
->FECharge
);
1613 p_start
= UDFPartStart(Vcb
, PartNum
);
1614 p_end
= UDFPartEnd(Vcb
, PartNum
);
1615 fe_loc
= DirInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
;
1617 status
= UDFGetCachedAllocation(Vcb
, fe_loc
, Ext
, NULL
, UDF_PREALLOC_CLASS_FE
);
1618 if(OS_SUCCESS(status
)) {
1619 // do nothing, even do not unpack
1621 if(Vcb
->LowFreeSpace
) {
1622 status
= UDFAllocFreeExtent(Vcb
, Len
<< Vcb
->LBlockSizeBits
,p_start
, p_end
, FEExtInfo
, EXTENT_FLAG_VERIFY
);
1623 if(OS_SUCCESS(status
)) {
1624 KdPrint(("FE @ %x (1)\n", FEExtInfo
->Mapping
[0].extLocation
));
1628 if(fe_loc
> p_start
+ 512*16) {
1629 l1
= fe_loc
- 512*16;
1633 if(fe_loc
+ 512*16 < p_end
) {
1634 l2
= fe_loc
+ 512*16;
1638 status
= UDFAllocFreeExtent(Vcb
, lim
<< Vcb
->LBlockSizeBits
, l1
, l2
, Ext
, EXTENT_FLAG_VERIFY
);
1639 if(!OS_SUCCESS(status
)) {
1640 status
= UDFAllocFreeExtent(Vcb
, lim
<< Vcb
->LBlockSizeBits
, (p_start
+fe_loc
)/2, (fe_loc
+p_end
)/2, Ext
, EXTENT_FLAG_VERIFY
);
1642 if(!OS_SUCCESS(status
)) {
1643 status
= UDFAllocFreeExtent(Vcb
, lim
<< Vcb
->LBlockSizeBits
, p_start
, p_end
, Ext
, EXTENT_FLAG_VERIFY
);
1645 if(!OS_SUCCESS(status
)) {
1646 status
= UDFAllocFreeExtent(Vcb
, lim
<< Vcb
->LBlockSizeBits
, p_start
+1024, p_end
-1024, Ext
, EXTENT_FLAG_VERIFY
);
1648 if(!OS_SUCCESS(status
= UDFAllocFreeExtent(Vcb
, lim
<< Vcb
->LBlockSizeBits
, p_start
, p_end
, Ext
, EXTENT_FLAG_VERIFY
) )) {
1649 // can't pre-allocate space for multiple FEs. Try single FE
1650 KdPrint(("allocate single FE entry\n"));
1651 status
= UDFAllocFreeExtent(Vcb
, Len
,
1652 p_start
, p_end
, FEExtInfo
, EXTENT_FLAG_VERIFY
);
1653 if(OS_SUCCESS(status
)) {
1654 KdPrint(("FE @ %x (2)\n", FEExtInfo
->Mapping
[0].extLocation
));
1658 status
= UDFUnPackMapping(Vcb
, Ext
);
1659 if(!OS_SUCCESS(status
)) {
1660 MyFreePool__(Ext
->Mapping
);
1661 Ext
->Mapping
= NULL
;
1667 for(i
=0;i
<lim
;i
++) {
1668 if( (Ext
->Mapping
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_ALLOCATED
) {
1669 Ext
->Mapping
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
; // EXTENT_RECORDED_ALLOCATED
1671 Extent
.extLength
= Vcb
->LBlockSize
| (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1672 Extent
.extLocation
= Ext
->Mapping
[i
].extLocation
;
1674 if(Vcb
->BSBM_Bitmap
) {
1675 uint32 lba
= Ext
->Mapping
[i
].extLocation
;
1676 if(UDFGetBadBit((uint32
*)(Vcb
->BSBM_Bitmap
), lba
)) {
1677 KdPrint(("Remove BB @ %x from FE charge\n", lba
));
1678 Ext
->Mapping
[i
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
1679 Ext
->Mapping
[i
].extLocation
= 0;
1684 FEExtInfo
->Mapping
= UDFExtentToMapping(&Extent
);
1685 if(!FEExtInfo
->Mapping
) {
1686 ASSERT(!(Ext
->Mapping
[i
].extLength
>> 30));
1687 Ext
->Mapping
[i
].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1688 return STATUS_INSUFFICIENT_RESOURCES
;
1690 KdPrint(("FE @ %x (3)\n", FEExtInfo
->Mapping
[0].extLocation
));
1691 FEExtInfo
->Length
= Len
;
1692 FEExtInfo
->Offset
= 0;
1693 FEExtInfo
->Modified
= TRUE
;
1694 return STATUS_SUCCESS
;
1698 if(Vcb
->LowFreeSpace
) {
1699 status
= UDFAllocFreeExtent(Vcb
, Len
,
1700 UDFPartStart(Vcb
, PartNum
), UDFPartEnd(Vcb
, PartNum
), FEExtInfo
, EXTENT_FLAG_VERIFY
);
1701 if(OS_SUCCESS(status
)) {
1702 KdPrint(("FE @ %x (4)\n", FEExtInfo
->Mapping
[0].extLocation
));
1707 return STATUS_INSUFFICIENT_RESOURCES
;
1709 // we can get here if there are no free slots in
1710 // preallocated FE charge. So, we should release
1711 // memory and try to allocate space for new FE charge.
1712 MyFreePool__(Ext
->Mapping
);
1713 Ext
->Mapping
= NULL
;
1716 return STATUS_INSUFFICIENT_RESOURCES
;
1717 #endif // UDF_FE_ALLOCATION_CHARGE
1719 } // end UDFAllocateFESpace()
1722 This routine frees space allocated for FE.
1727 IN PUDF_FILE_INFO DirInfo
,
1728 IN PEXTENT_INFO FEExtInfo
1731 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE
1733 uint32 i
, lim
, j
=-1;
1736 // check if the DirInfo we are called with is a Directory
1737 // (it can be a file with SDir)
1738 if(DirInfo
&& DirInfo
->Dloc
->DirIndex
&&
1739 (Ext
= &(DirInfo
->Dloc
->DirIndex
->FECharge
))->Mapping
) {
1740 if(!FEExtInfo
->Mapping
)
1742 Lba
= FEExtInfo
->Mapping
[0].extLocation
;
1744 lim
= (DirInfo
->Dloc
->FE_Flags
& UDF_FE_FLAG_IS_SDIR
) ? Vcb
->FEChargeSDir
: Vcb
->FECharge
;
1745 for(i
=0;i
<lim
;i
++) {
1746 if(Ext
->Mapping
[i
].extLocation
== Lba
) {
1747 ASSERT(!(Ext
->Mapping
[i
].extLength
>> 30));
1748 Ext
->Mapping
[i
].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1751 if(!Ext
->Mapping
[i
].extLocation
) {
1755 if(j
!= (ULONG
)-1) {
1757 Ext
->Mapping
[i
].extLocation
= Lba
;
1758 Ext
->Mapping
[i
].extLength
= Vcb
->LBlockSize
| (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1762 #endif // UDF_FE_ALLOCATION_CHARGE
1763 UDFMarkSpaceAsXXX(Vcb
, 0, FEExtInfo
->Mapping
, AS_DISCARDED
); // free
1765 FEExtInfo
->Mapping
[0].extLocation
= 0;
1766 FEExtInfo
->Mapping
[0].extLength
= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
1768 } // end UDFFreeFESpace()
1769 #endif //UDF_READ_ONLY_BUILD
1772 This routine flushes FE-Charge buffer, marks unused blocks as free
1773 in bitmap & releases memory allocated for FE-Charge management
1778 IN PUDF_DATALOC_INFO Dloc
,
1782 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE
1783 PEXTENT_MAP Mapping
;
1786 if(!(Mapping
= Dloc
->DirIndex
->FECharge
.Mapping
))
1789 lim
= (Dloc
->FE_Flags
& UDF_FE_FLAG_IS_SDIR
) ? Vcb
->FEChargeSDir
: Vcb
->FECharge
;
1793 if(OS_SUCCESS(UDFStoreCachedAllocation(Vcb
,
1794 Dloc
->FELoc
.Mapping
[0].extLocation
,
1795 &Dloc
->DirIndex
->FECharge
, lim
, UDF_PREALLOC_CLASS_FE
))) {
1796 Dloc
->DirIndex
->FECharge
.Mapping
= NULL
;
1800 Dloc
->DirIndex
->FECharge
.Mapping
= NULL
;
1801 UDFDiscardFESpace(Vcb
, Mapping
, lim
);
1802 #else // UDF_FE_ALLOCATION_CHARGE
1803 ASSERT(!Dloc
->DirIndex
->FECharge
.Mapping
);
1805 #endif // UDF_FE_ALLOCATION_CHARGE
1806 } // end UDFFlushFESpace()
1808 #ifndef UDF_READ_ONLY_BUILD
1810 This routine rebuilds mapping on write attempts to Alloc-Not-Rec area.
1811 Here we assume that required area lays in a single frag.
1814 UDFMarkAllocatedAsRecorded(
1818 IN PEXTENT_INFO ExtInfo
// Extent array
1821 uint32 i
, len
, lba
, sLen
;
1822 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
1823 PEXTENT_MAP NewExtent
;
1824 uint32 BS
= Vcb
->BlockSize
;
1825 uint32 LBS
= Vcb
->LBlockSize
;
1826 uint32 BSh
= Vcb
->BlockSizeBits
;
1827 BOOLEAN TryPack
= TRUE
;
1831 // I don't know what else comment can be added here.
1832 // Just belive that it works
1833 lba
= UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, (Offset
& ~((int64
)LBS
-1)), NULL
, NULL
, NULL
, &i
);
1834 if(i
== (ULONG
)-1) return STATUS_INVALID_PARAMETER
;
1836 check_size
= UDFGetExtentLength(ExtInfo
->Mapping
);
1837 ASSERT(!(check_size
& (LBS
-1)));
1839 AdPrint(("Alloc->Rec ExtInfo %x, Extent %x\n", ExtInfo
, Extent
));
1840 if((Extent
[i
].extLength
>> 30) == EXTENT_RECORDED_ALLOCATED
) return STATUS_SUCCESS
;
1841 if((Extent
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) return STATUS_INVALID_PARAMETER
;
1842 ASSERT((((uint32
)Offset
) & (LBS
-1)) + Length
<= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
));
1843 sLen
= (( (((uint32
)Offset
) & (LBS
-1)) + Length
+LBS
-1) & ~(LBS
-1)) >> BSh
;
1844 if((Extent
[i
].extLocation
== lba
) && (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) == sLen
)) {
1846 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1847 // Extent[i].extLength |= (EXTENT_RECORDED_ALLOCATED << 30); // = 0;
1848 ExtInfo
->Modified
= TRUE
;
1850 ((Extent
[i
-1].extLength
>> 30) == EXTENT_RECORDED_ALLOCATED
) &&
1851 (lba
== (Extent
[i
-1].extLocation
+ ((len
= Extent
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
))) &&
1852 ((len
+ (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)) <= UDF_MAX_EXTENT_LENGTH
) &&
1853 (i
== ((UDFGetMappingLength(Extent
) / sizeof(EXTENT_MAP
)) - 2)) &&
1855 // make optimization for sequentially written files
1856 Extent
[i
-1].extLength
+= Extent
[i
].extLength
;
1857 Extent
[i
].extLocation
= 0;
1858 Extent
[i
].extLength
= 0;
1860 UDFPackMapping(Vcb
, ExtInfo
);
1862 AdPrint(("Alloc->Rec (1) new %x\n", ExtInfo
->Mapping
));
1864 ASSERT(check_size
== UDFGetExtentLength(ExtInfo
->Mapping
));
1866 AdPrint(("Alloc->Rec: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
1867 return STATUS_SUCCESS
;
1869 if(Extent
[i
].extLocation
< lba
) {
1870 if( (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) - (lba
- Extent
[i
].extLocation
))
1873 NewExtent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
)*2,
1875 if(!NewExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
1876 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1877 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
1878 RtlCopyMemory((int8
*)&(NewExtent
[i
+3]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
1879 NewExtent
[i
].extLocation
= Extent
[i
].extLocation
;
1880 NewExtent
[i
].extLength
= (lba
- Extent
[i
].extLocation
) << BSh
;
1881 NewExtent
[i
+1].extLength
= (Length
+BS
-1) & ~(BS
-1);
1882 NewExtent
[i
+1].extLocation
= lba
;
1883 NewExtent
[i
+2].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
- NewExtent
[i
+1].extLength
;
1884 NewExtent
[i
+2].extLocation
= lba
+ ((Length
+BS
-1) >> BSh
);
1885 ASSERT(!(NewExtent
[i
].extLength
>> 30));
1886 ASSERT(!(NewExtent
[i
+2].extLength
>> 30));
1887 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1888 NewExtent
[i
+2].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1890 AdPrint(("Alloc->Rec (2) new %x\n", NewExtent
));
1893 NewExtent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
),
1895 if(!NewExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
1896 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1897 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
1898 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
1899 NewExtent
[i
].extLocation
= Extent
[i
].extLocation
;
1900 NewExtent
[i
].extLength
= (lba
- Extent
[i
].extLocation
) << BSh
;
1901 NewExtent
[i
+1].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
;
1902 NewExtent
[i
+1].extLocation
= lba
;
1903 ASSERT(!(NewExtent
[i
].extLength
>> 30));
1904 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1905 AdPrint(("Alloc->Rec (3) new %x\n", NewExtent
));
1909 NewExtent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
),
1911 if(!NewExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
1912 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1913 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
1914 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
1915 NewExtent
[i
].extLocation
= Extent
[i
].extLocation
;
1916 NewExtent
[i
].extLength
= (Length
+BS
-1) & ~(BS
-1);
1917 NewExtent
[i
+1].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
;
1918 NewExtent
[i
+1].extLocation
= Extent
[i
].extLocation
+ (NewExtent
[i
].extLength
>> BSh
);
1919 ASSERT(!(NewExtent
[i
+1].extLength
>> 30));
1920 NewExtent
[i
+1].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1921 AdPrint(("Alloc->Rec (4) new %x\n", NewExtent
));
1924 //ASSERT(check_size == UDFGetExtentLength(Extent));
1925 //ASSERT(!(check_size & (LBS-1)));
1927 AdPrint(("Free Extent %x (new %x)\n", Extent
, NewExtent
));
1928 MyFreePool__(Extent
);
1929 ExtInfo
->Modified
= TRUE
;
1930 ExtInfo
->Mapping
= NewExtent
;
1932 UDFPackMapping(Vcb
, ExtInfo
);
1934 ASSERT(check_size
== UDFGetExtentLength(ExtInfo
->Mapping
));
1935 ASSERT(!(check_size
& (LBS
-1)));
1938 AdPrint(("Alloc->Rec: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
1940 return STATUS_SUCCESS
;
1941 } // end UDFMarkAllocatedAsRecorded()
1944 This routine rebuilds mapping on write attempts to Not-Alloc-Not-Rec area.
1945 Here we assume that required area lays in a single frag.
1948 UDFMarkNotAllocatedAsAllocated(
1952 IN PEXTENT_INFO ExtInfo
// Extent array
1955 uint32 i
, len
, /*lba,*/ d
, l
, BOffs
, j
;
1956 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
1957 PEXTENT_MAP NewExtent
;
1958 // uint32 BS = Vcb->BlockSize;
1959 uint32 BSh
= Vcb
->BlockSizeBits
;
1961 EXTENT_INFO TmpExtInf
;
1963 uint32 LBS
= Vcb
->LBlockSize
;
1964 // I don't know what else comment can be added here.
1965 // Just belive that it works
1967 #ifndef ALLOW_SPARSE
1970 AdPrint(("Not->Alloc ExtInfo %x, Extent %x\n", ExtInfo
, Extent
));
1971 UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Offset
, NULL
, NULL
, NULL
, &i
);
1972 if(i
== (ULONG
)-1) return STATUS_INVALID_PARAMETER
;
1973 if((Extent
[i
].extLength
>> 30) != EXTENT_NOT_RECORDED_NOT_ALLOCATED
) return STATUS_SUCCESS
;
1975 uint32 PartNum
= UDFGetPartNumByPhysLba(Vcb
, Extent
[0].extLocation
);
1976 BOffs
= (uint32
)(Offset
>> BSh
);
1977 // length of existing Not-Alloc-Not-Rec frag
1978 sLen
= (( (((uint32
)Offset
) & (LBS
-1)) + Length
+LBS
-1) & ~(LBS
-1)) >> BSh
;
1979 // required allocation length increment (in bytes)
1980 aLen
= (uint32
)( ((Offset
+Length
+LBS
-1) & ~(LBS
-1)) - (Offset
& ~(LBS
-1)));
1982 // try to extend previous frag or allocate space _after_ it to
1983 // avoid backward seeks, if previous frag is not Not-Rec-Not-Alloc
1984 if(i
&& ((Extent
[i
-1].extLength
>> 30) != EXTENT_NOT_RECORDED_NOT_ALLOCATED
) ) {
1985 status
= UDFAllocFreeExtent(Vcb
, aLen
,
1986 Extent
[i
-1].extLocation
+ ((Extent
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
),
1987 min(UDFPartEnd(Vcb
, PartNum
), Extent
[i
-1].extLocation
+ ((Extent
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) + sLen
),
1988 &TmpExtInf
, ExtInfo
->Flags
/*& EXTENT_FLAG_ALLOC_MASK*/);
1989 if(status
== STATUS_DISK_FULL
)
1990 // if there are not enough free blocks after that frag...
1991 goto try_alloc_anywhere
;
1994 // ... try to alloc required disk space anywhere
1995 status
= UDFAllocFreeExtent(Vcb
, aLen
,
1996 UDFPartStart(Vcb
, PartNum
),
1997 UDFPartEnd(Vcb
, PartNum
),
1998 &TmpExtInf
, ExtInfo
->Flags
/*& EXTENT_FLAG_ALLOC_MASK*/);
2000 // check for successfull allocation
2001 if(!OS_SUCCESS(status
)) {
2002 AdPrint(("Not->Alloc no free\n"));
2005 // get number of frags in allocated block
2006 d
= (UDFGetMappingLength(TmpExtInf
.Mapping
) / sizeof(EXTENT_MAP
)) - 1;
2007 // calculate number of existing blocks before the frag to be changed
2009 for(j
=0; j
<i
; j
++) {
2010 l
+= (uint32
)((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2012 // and now just update mapping...
2013 if( (l
== BOffs
) && (((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) == sLen
) ) {
2015 // (d-1) - since we have to raplace last frag of Extent with 1 or more frags of TmpExtInf.Mapping
2016 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + (d
-1)*sizeof(EXTENT_MAP
) );
2018 MyFreePool__(TmpExtInf
.Mapping
);
2019 return STATUS_INSUFFICIENT_RESOURCES
;
2021 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2022 RtlCopyMemory((int8
*)&(NewExtent
[i
]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2023 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2024 AdPrint(("Not->Alloc (1) new %x\n", NewExtent
));
2027 // .ExtLength, BOffs & l are already aligned...
2028 if( (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) - (BOffs
-l
)) > sLen
) {
2030 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + (d
+1)*sizeof(EXTENT_MAP
) );
2032 MyFreePool__(TmpExtInf
.Mapping
);
2033 return STATUS_INSUFFICIENT_RESOURCES
;
2035 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2036 RtlCopyMemory((int8
*)&(NewExtent
[i
+1]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2037 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2038 NewExtent
[i
].extLocation
= 0;
2039 NewExtent
[i
].extLength
= (BOffs
- l
) << BSh
;
2040 NewExtent
[i
+d
+1].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
- aLen
;
2041 NewExtent
[i
+d
+1].extLocation
= 0;
2042 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2043 NewExtent
[i
+d
+1].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2044 AdPrint(("Not->Alloc (2) new %x\n", NewExtent
));
2047 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + d
*sizeof(EXTENT_MAP
) );
2049 MyFreePool__(TmpExtInf
.Mapping
);
2050 return STATUS_INSUFFICIENT_RESOURCES
;
2052 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2053 RtlCopyMemory((int8
*)&(NewExtent
[i
+1]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2054 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
+1]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2055 NewExtent
[i
].extLocation
= 0;
2056 NewExtent
[i
].extLength
= (BOffs
- l
) << BSh
;
2057 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2058 AdPrint(("Not->Alloc (3) new %x\n", NewExtent
));
2062 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + d
*sizeof(EXTENT_MAP
) );
2064 MyFreePool__(TmpExtInf
.Mapping
);
2065 return STATUS_INSUFFICIENT_RESOURCES
;
2067 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2068 RtlCopyMemory((int8
*)&(NewExtent
[i
]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2069 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
+1]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2070 NewExtent
[i
+d
].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) - aLen
;
2071 NewExtent
[i
+d
].extLocation
= 0;
2072 NewExtent
[i
+d
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2073 AdPrint(("Not->Alloc (4) new %x\n", NewExtent
));
2076 AdPrint(("Free Extent %x, TmpExtInf.Mapping, (new %x)\n", Extent
, TmpExtInf
.Mapping
, NewExtent
));
2077 MyFreePool__(Extent
);
2078 MyFreePool__(TmpExtInf
.Mapping
);
2079 ExtInfo
->Modified
= TRUE
;
2080 ExtInfo
->Mapping
= NewExtent
;
2082 AdPrint(("Not->Alloc: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
2084 return STATUS_SUCCESS
;
2085 } // end UDFMarkNotAllocatedAsAllocated()
2089 This routine rebuilds mapping on write zero attempts to
2091 Here we assume that required area lays in a single frag.
2094 UDFMarkAllocatedAsNotXXX(
2098 IN PEXTENT_INFO ExtInfo
, // Extent array
2099 IN BOOLEAN Deallocate
2102 uint32 i
, len
, /*lba, d,*/ l
, BOffs
, j
;
2103 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
2104 PEXTENT_MAP NewExtent
;
2105 // EXTENT_MAP TmpExtent;
2106 // uint32 BS = Vcb->BlockSize;
2107 uint32 BSh
= Vcb
->BlockSizeBits
;
2109 EXTENT_INFO TmpExtInf
;
2112 uint32 target_flags
= Deallocate
?
2113 EXTENT_NOT_RECORDED_NOT_ALLOCATED
:
2114 EXTENT_NOT_RECORDED_ALLOCATED
;
2115 uint32 LBS
= Vcb
->LBlockSize
;
2116 EXTENT_MAP DeadMapping
[2];
2117 // I don't know what else comment can be added here.
2118 // Just belive that it works
2120 #ifndef ALLOW_SPARSE
2126 AdPrint(("Alloc->Not ExtInfo %x, Extent %x\n", ExtInfo
, Extent
));
2128 DeadMapping
[0].extLocation
=
2129 UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Offset
, NULL
, NULL
, NULL
, &i
);
2130 if(i
== (ULONG
)-1) {
2132 return STATUS_INVALID_PARAMETER
;
2134 DeadMapping
[0].extLength
= Extent
[i
].extLength
;
2135 DeadMapping
[1].extLocation
=
2136 DeadMapping
[1].extLength
= 0;
2137 TmpExtInf
.Mapping
= (PEXTENT_MAP
)&DeadMapping
;
2138 TmpExtInf
.Offset
= 0;
2139 TmpExtInf
.Length
= Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2141 flags
= Extent
[i
].extLength
>> 30;
2142 if(flags
== target_flags
) return STATUS_SUCCESS
;
2144 // uint32 PartNum = UDFGetPartNumByPhysLba(Vcb, Extent[0].extLocation);
2145 BOffs
= (uint32
)(Offset
>> BSh
);
2146 // length of existing Alloc-(Not-)Rec frag (in sectors)
2147 sLen
= (( (((uint32
)Offset
) & (LBS
-1)) + Length
+LBS
-1) & ~(LBS
-1)) >> BSh
;
2148 // required deallocation length increment (in bytes)
2149 aLen
= (uint32
)( ((Offset
+Length
+LBS
-1) & ~(LBS
-1)) - (Offset
& ~(LBS
-1)) );
2152 for(j
=0; j
<i
; j
++) {
2153 l
+= (uint32
)((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2156 if( (l
== BOffs
) && (((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) == sLen
) ) {
2158 Extent
[i
].extLocation
= 0;
2159 Extent
[i
].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) | flags
;
2161 AdPrint(("Alloc->Not (1) NewExtent = Extent = %x\n", NewExtent
));
2164 // .ExtLength, BOffs & l are already aligned...
2165 if( (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) - (BOffs
-l
)) > sLen
) {
2167 NewExtent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + 2*sizeof(EXTENT_MAP
) );
2169 return STATUS_INSUFFICIENT_RESOURCES
;
2171 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2172 RtlCopyMemory((int8
*)&(NewExtent
[i
+3]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2173 NewExtent
[i
].extLength
= (BOffs
- l
) << BSh
;
2174 NewExtent
[i
].extLength
|= flags
;
2175 NewExtent
[i
+1].extLocation
= 0;
2176 NewExtent
[i
+1].extLength
= aLen
| (target_flags
<< 30);
2177 NewExtent
[i
+2].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) -
2178 (NewExtent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) - aLen
;
2179 NewExtent
[i
+2].extLocation
= Extent
[i
].extLocation
+
2180 (NewExtent
[i
+2].extLength
>> BSh
);
2181 NewExtent
[i
+2].extLength
|= flags
;
2182 AdPrint(("Alloc->Not (2) new %x\n", NewExtent
));
2185 NewExtent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
) );
2187 return STATUS_INSUFFICIENT_RESOURCES
;
2189 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2190 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2191 NewExtent
[i
].extLength
= ((BOffs
- l
) << BSh
) | flags
;
2192 NewExtent
[i
+1].extLocation
= 0;
2193 NewExtent
[i
+1].extLength
= aLen
| (target_flags
<< 30);
2194 AdPrint(("Alloc->Not (3) new %x\n", NewExtent
));
2198 NewExtent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
) );
2200 return STATUS_INSUFFICIENT_RESOURCES
;
2202 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2203 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2204 NewExtent
[i
+1].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) - aLen
;
2205 NewExtent
[i
+1].extLength
|= flags
;
2206 NewExtent
[i
].extLocation
= 0;
2207 NewExtent
[i
].extLength
= aLen
| (target_flags
<< 30);
2208 AdPrint(("Alloc->Not (4) new %x\n", NewExtent
));
2212 UDFMarkSpaceAsXXX(Vcb
, (-1), TmpExtInf
.Mapping
, AS_DISCARDED
); // mark as free
2215 AdPrint(("Alloc->Not kill %x\n", Extent
));
2216 MyFreePool__(Extent
);
2218 AdPrint(("Alloc->Not keep %x\n", Extent
));
2220 ExtInfo
->Modified
= TRUE
;
2221 ExtInfo
->Mapping
= NewExtent
;
2222 AdPrint(("Alloc->Not: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
2224 return STATUS_SUCCESS
;
2225 } // end UDFMarkAllocatedAsNotXXX()
2229 This routine resizes extent & updates associated mapping
2235 IN int64 Length
, // Required Length
2236 IN BOOLEAN AlwaysInIcb
, // must be TRUE for AllocDescs
2237 OUT PEXTENT_INFO ExtInfo
2240 uint32 i
, flags
, lba
, lim
;
2243 EXTENT_INFO TmpExtInf
;
2244 EXTENT_MAP TmpMapping
[2];
2245 uint32 s
, req_s
, pe
, BSh
, LBS
, PS
;
2246 LBS
= Vcb
->LBlockSize
;
2247 BSh
= Vcb
->BlockSizeBits
;
2248 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
2249 uint32 MaxGrow
= (UDF_MAX_EXTENT_LENGTH
& ~(LBS
-1));
2250 BOOLEAN Sequential
= FALSE
;
2252 ASSERT(PartNum
< 3);
2254 ExtPrint(("Resize ExtInfo %x, %I64x -> %I64x\n", ExtInfo
, ExtInfo
->Length
, Length
));
2256 if(ExtInfo
->Flags
& EXTENT_FLAG_CUT_PREALLOCATED
) {
2257 AdPrint((" cut preallocated\n"));
2259 if(ExtInfo
->Length
== Length
) {
2260 return STATUS_SUCCESS
;
2262 if((ExtInfo
->Flags
& EXTENT_FLAG_ALLOC_MASK
) == EXTENT_FLAG_ALLOC_SEQUENTIAL
) {
2263 MaxGrow
&= ~(Vcb
->WriteBlockSize
-1);
2267 UDFCheckSpaceAllocation(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // check if used
2268 if(ExtInfo
->Offset
) {
2269 if(ExtInfo
->Offset
+ Length
<= LBS
) {
2270 ExtPrint(("Resize IN-ICB\n"));
2271 ExtInfo
->Length
= Length
;
2272 return STATUS_SUCCESS
;
2274 if(!AlwaysInIcb
) // simulate unused 1st sector in extent
2275 ExtInfo
->Offset
= LBS
; // it'll be truncated later
2276 Length
+= ExtInfo
->Offset
; // convert to real offset in extent
2278 lba
= UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Length
, NULL
, NULL
, &flags
, &i
);
2279 if(ExtInfo
->Length
< Length
) {
2281 if(OS_SUCCESS(UDFGetCachedAllocation(Vcb
, ExtInfo
->Mapping
[0].extLocation
,
2282 &TmpExtInf
, NULL
, UDF_PREALLOC_CLASS_DIR
))) {
2283 AdPrint(("Resize found cached(1)\n"));
2284 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, TmpExtInf
.Mapping
);
2285 MyFreePool__(TmpExtInf
.Mapping
);
2287 if((l
= UDFGetExtentLength(ExtInfo
->Mapping
)) >= Length
) {
2288 // we have enough space inside extent
2289 ExtInfo
->Length
= Length
;
2290 AdPrint(("Resize do nothing (1)\n"));
2291 } else /*if(lba == LBA_OUT_OF_EXTENT)*/ {
2293 Length
-= ExtInfo
->Offset
;
2294 if(/*Length && l &&*/ (l
% MaxGrow
) &&
2295 (Length
-1)/MaxGrow
!= (l
-1)/MaxGrow
) {
2296 AdPrint(("Crossing MAX_FRAG boundary...\n"));
2297 int64 l2
= ((l
-1)/MaxGrow
+ 1)*MaxGrow
;
2298 status
= UDFResizeExtent(Vcb
, PartNum
, l2
, AlwaysInIcb
, ExtInfo
);
2299 if(!OS_SUCCESS(status
)) {
2300 KdPrint(("Sub-call to UDFResizeExtent() failed (%x)\n", status
));
2303 l
= ExtInfo
->Length
;
2306 while((Length
- l
) > MaxGrow
) {
2307 status
= UDFResizeExtent(Vcb
, PartNum
, l
+MaxGrow
, AlwaysInIcb
, ExtInfo
);
2308 if(!OS_SUCCESS(status
)) {
2309 KdPrint(("Sub-call (2) to UDFResizeExtent() failed (%x)\n", status
));
2312 l
= ExtInfo
->Length
;
2314 Length
+= ExtInfo
->Offset
;
2315 // at first, try to resize existing frag
2316 #ifndef UDF_ALLOW_FRAG_AD
2317 i
= UDFGetMappingLength(ExtInfo
->Mapping
);
2318 if(i
> (LBS
-sizeof(EXTENDED_FILE_ENTRY
))) {
2319 // this is very important check since we will not
2320 // be able to _record_ too long AllocDesc because of
2321 // some DEMO limitations in UDFBuildXXXAllocDescs()
2322 AdPrint((" DISK_FULL\n"));
2323 return STATUS_DISK_FULL
;
2325 i
/= sizeof(EXTENT_MAP
);
2326 #else //UDF_ALLOW_FRAG_AD
2327 i
= UDFGetMappingLength(ExtInfo
->Mapping
) / sizeof(EXTENT_MAP
);
2328 #endif //UDF_ALLOW_FRAG_AD
2330 if(!AlwaysInIcb
&& !(ExtInfo
->Offset
) &&
2331 (Length
- l
>= (Vcb
->SparseThreshold
<< BSh
))) {
2332 // last frag will be Not-Alloc-Not-Rec...
2333 AdPrint(("Resize sparse (2)\n"));
2334 RtlZeroMemory(&TmpExtInf
, sizeof(EXTENT_INFO
));
2335 TmpExtInf
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, sizeof(EXTENT_MAP
)*2,
2337 if(!TmpExtInf
.Mapping
) return STATUS_INSUFFICIENT_RESOURCES
;
2338 TmpExtInf
.Mapping
[0].extLength
= (((uint32
)(Length
- l
) + LBS
-1) & ~(LBS
-1)) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2339 TmpExtInf
.Mapping
[0].extLocation
=// 0;
2340 TmpExtInf
.Mapping
[1].extLength
=
2341 TmpExtInf
.Mapping
[1].extLocation
= 0;
2343 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, TmpExtInf
.Mapping
);
2344 MyFreePool__(TmpExtInf
.Mapping
);
2346 #endif //ALLOW_SPARSE
2347 // allocate some sectors
2348 if(i
>1 && !(ExtInfo
->Offset
)) {
2350 // check if Not-Alloc-Not-Rec at the end of mapping
2351 if((uint32
)Length
- (uint32
)l
+ (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) > MaxGrow
) {
2352 // do nothing, but jump directly to allocator
2354 if((ExtInfo
->Mapping
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
2355 AdPrint(("Resize grow sparse (3)\n"));
2356 ExtInfo
->Mapping
[i
].extLength
+=
2357 (((uint32
)Length
-(uint32
)l
+LBS
-1) & ~(LBS
-1)) ;
2359 // check if Alloc-Not-Rec at the end of mapping
2360 } else if((ExtInfo
->Mapping
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_ALLOCATED
) {
2361 AdPrint(("Resize grow Not-Rec (3)\n"));
2362 // current length of last frag
2363 s
= ((ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2364 // prefered location of the next frag
2365 lba
= ExtInfo
->Mapping
[i
].extLocation
+ s
;
2366 pe
=UDFPartEnd(Vcb
,PartNum
);
2367 // maximum frag length
2369 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(PS
-1);
2371 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(LBS
-1);
2373 // required last extent length
2374 req_s
= s
+ (uint32
)( (((Length
+ LBS
- 1) & ~(LBS
-1)) -
2375 ((l
+ LBS
- 1) & ~(LBS
-1)) ) >> BSh
);
2379 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
2380 /* if((ExtInfo->Flags & EXTENT_FLAG_SEQUENTIAL) &&
2381 ((Length & ~(PS-1)) > (l & ~(PS-1))) &&
2383 status = UDFResizeExtent(Vcb, PartNum, l+MaxGrow, AlwaysInIcb, ExtInfo);
2385 // how many sectors we should add
2388 if((lba
< pe
) && UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
)) {
2389 s
+= UDFGetBitmapLen((uint32
*)(Vcb
->FSBM_Bitmap
), lba
, min(pe
, lba
+req_s
-1));
2391 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) {
2395 // we can just increase the last frag
2396 AdPrint(("Resize grow last Not-Rec (4)\n"));
2397 ExtInfo
->Mapping
[i
].extLength
= (lim
<< BSh
) | (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
2399 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_USED
); // mark as used
2401 // we get here if simple increasing of last frag failed
2402 // it worth truncating last frag and try to allocate
2403 // all required data as a single frag
2405 /* if(Sequential && s>=PS) {
2407 AdPrint(("Resize grow last Not-Rec (4/2)\n"));
2408 ExtInfo->Mapping[i].extLength = (s << BSh) | (EXTENT_NOT_RECORDED_ALLOCATED << 30);
2410 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // mark as used
2412 AdPrint(("Resize reloc last Not-Rec (5)\n"));
2413 TmpExtInf
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, (i
+1)*sizeof(EXTENT_MAP
),
2415 if(!TmpExtInf
.Mapping
) {
2416 KdPrint(("UDFResizeExtent: !TmpExtInf.Mapping\n"));
2417 UDFReleaseResource(&(Vcb
->BitMapResource1
));
2418 return STATUS_INSUFFICIENT_RESOURCES
;
2420 RtlCopyMemory(TmpExtInf
.Mapping
, ExtInfo
->Mapping
, i
*sizeof(EXTENT_MAP
));
2421 TmpExtInf
.Mapping
[i
].extLength
=
2422 TmpExtInf
.Mapping
[i
].extLocation
= 0;
2423 TmpExtInf
.Offset
= ExtInfo
->Offset
;
2424 l
-= (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
);
2425 TmpExtInf
.Length
= l
;
2426 ASSERT(i
|| !ExtInfo
->Offset
);
2427 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_DISCARDED
); // mark as free
2428 MyFreePool__(ExtInfo
->Mapping
);
2429 (*ExtInfo
) = TmpExtInf
;
2431 UDFCheckSpaceAllocation(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // check if used
2432 UDFReleaseResource(&(Vcb
->BitMapResource1
));
2433 // check if Alloc-Rec
2435 // current length of last frag
2436 s
= ((ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2437 // prefered location of the next frag
2438 lba
= ExtInfo
->Mapping
[i
].extLocation
+ s
;
2439 pe
=UDFPartEnd(Vcb
,PartNum
);
2440 // maximum frag length
2442 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(PS
-1);
2444 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(LBS
-1);
2446 // required last extent length
2447 req_s
= s
+ (uint32
)( (((Length
+ LBS
- 1) & ~(LBS
-1)) -
2448 ((l
+ LBS
- 1) & ~(LBS
-1)) ) >> BSh
);
2453 // how many sectors we should add
2458 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
2460 if((lba
< pe
) && UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
)) {
2461 s
+= (d
= UDFGetBitmapLen((uint32
*)(Vcb
->FSBM_Bitmap
), lba
, min(pe
, lba
+req_s
-1)));
2463 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) {
2468 AdPrint(("Resize grow last Rec (6)\n"));
2469 // we can just increase last frag
2470 TmpMapping
[0].extLength
= req_s
<< BSh
;
2471 TmpMapping
[0].extLocation
= lba
;
2472 TmpMapping
[1].extLength
=
2473 TmpMapping
[1].extLocation
= 0;
2474 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &TmpMapping
[0], AS_USED
); // mark as used
2475 l
+= (s
<< BSh
) - (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
);
2476 ExtInfo
->Mapping
[i
].extLength
= (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_FLAG_MASK
) | (s
<< BSh
);
2478 AdPrint(("Resize part-grow last Rec (6)\n"));
2479 // increase last frag, then alloc rest
2480 TmpMapping
[0].extLength
= d
<< BSh
;
2481 TmpMapping
[0].extLocation
= lba
;
2482 TmpMapping
[1].extLength
=
2483 TmpMapping
[1].extLocation
= 0;
2484 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &TmpMapping
[0], AS_USED
); // mark as used
2485 l
+= (s
<< BSh
) - (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
);
2486 ExtInfo
->Mapping
[i
].extLength
= (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_FLAG_MASK
) | (s
<< BSh
);
2488 AdPrint(("Can't grow last Rec (6)\n"));
2490 UDFReleaseResource(&(Vcb
->BitMapResource1
));
2492 AdPrint(("Max frag length reached (6)\n"));
2497 // we get here if simple increasing of the last frag failed
2498 AdPrint(("Resize add new frag (7)\n"));
2499 if(l
< LBS
&& Length
>= LBS
&&
2500 (ExtInfo
->Flags
& EXTENT_FLAG_ALLOC_MASK
) == EXTENT_FLAG_ALLOC_SEQUENTIAL
) {
2501 AdPrint(("Resize tune for SEQUENTIAL i/o\n"));
2503 status
= UDFAllocFreeExtent(Vcb
, Length
- l
,
2504 UDFPartStart(Vcb
, PartNum
),
2505 UDFPartEnd(Vcb
, PartNum
),
2507 ExtInfo
->Flags
/*& EXTENT_FLAG_ALLOC_MASK*/);
2508 if(!OS_SUCCESS(status
)) {
2509 KdPrint(("UDFResizeExtent: UDFAllocFreeExtent() failed (%x)\n", status
));
2512 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, TmpExtInf
.Mapping
);
2513 MyFreePool__(TmpExtInf
.Mapping
);
2515 UDFPackMapping(Vcb
, ExtInfo
);
2520 AdPrint(("Resize cut (8)\n"));
2521 lba
= UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Length
-1, NULL
, &lim
, &flags
, &i
);
2523 ASSERT(lba
!= LBA_OUT_OF_EXTENT
);
2524 ASSERT(lba
!= LBA_NOT_ALLOCATED
);
2526 if(ExtInfo
->Mapping
[i
].extLength
) {
2527 UDFCheckSpaceAllocation(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_USED
); // check if used
2528 if(!ExtInfo
->Offset
&& (ExtInfo
->Flags
& EXTENT_FLAG_PREALLOCATED
)) {
2530 AdPrint(("Resize try save cutted (8)\n"));
2531 RtlZeroMemory(&TmpExtInf
, sizeof(EXTENT_INFO
));
2532 s
= UDFGetMappingLength(&(ExtInfo
->Mapping
[i
]));
2534 TmpExtInf
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, s
, MEM_EXTMAP_TAG
);
2535 if(TmpExtInf
.Mapping
) {
2536 RtlCopyMemory(TmpExtInf
.Mapping
, &(ExtInfo
->Mapping
[i
]), s
);
2537 AdPrint(("Resize save cutted (8)\n"));
2538 if(OS_SUCCESS(UDFStoreCachedAllocation(Vcb
, ExtInfo
->Mapping
[0].extLocation
,
2539 &TmpExtInf
, 0, UDF_PREALLOC_CLASS_DIR
))) {
2540 ExtInfo
->Mapping
[i
].extLength
= 0;
2541 ExtInfo
->Mapping
[i
].extLocation
= 0;
2546 UDFMarkSpaceAsXXX(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_DISCARDED
); // mark as free
2549 if((lim
-1 >= LBS
) &&
2550 (flags
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
)) {
2551 AdPrint(("i=%x, lba=%x, len=%x\n",i
,lba
,lim
));
2554 EXTENT_MAP ClrMap
[2];
2555 ClrMap
[0].extLength
= lim
& ~(LBS
-1);
2556 s
= (ExtInfo
->Mapping
[i
-1].extLength
- ClrMap
[0].extLength
) & UDF_EXTENT_LENGTH_MASK
;
2557 ClrMap
[0].extLocation
= ExtInfo
->Mapping
[i
-1].extLocation
+
2559 ClrMap
[1].extLength
=
2560 ClrMap
[1].extLocation
= 0;
2561 ASSERT((ExtInfo
->Mapping
[i
].extLocation
< ClrMap
[0].extLocation
) ||
2562 (ExtInfo
->Mapping
[i
].extLocation
>= (ClrMap
[0].extLocation
+ (ClrMap
[0].extLength
>> BSh
))));
2563 UDFCheckSpaceAllocation(Vcb
, 0, (PEXTENT_MAP
)(&ClrMap
), AS_USED
); // check if used
2564 UDFMarkSpaceAsXXX(Vcb
, 0, (PEXTENT_MAP
)(&ClrMap
), AS_DISCARDED
); // mark as free
2565 ExtInfo
->Mapping
[i
-1].extLength
= s
| (flags
<< 30);
2568 s
= UDFGetMappingLength(ExtInfo
->Mapping
);
2569 if(!MyReallocPool__((int8
*)(ExtInfo
->Mapping
), s
, (int8
**)&(ExtInfo
->Mapping
), (i
+1)*sizeof(EXTENT_MAP
))) {
2570 // This must never happen on truncate !!!
2571 AdPrint(("ResizeExtent: MyReallocPool__(8) failed\n"));
2573 ExtInfo
->Mapping
[i
].extLength
=
2574 ExtInfo
->Mapping
[i
].extLocation
= 0;
2576 AdPrint(("Resize zero (9)\n"));
2577 ASSERT(!ExtInfo
->Offset
);
2578 UDFMarkSpaceAsXXX(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // mark as free
2579 s
= UDFGetMappingLength(ExtInfo
->Mapping
);
2580 if(!MyReallocPool__((int8
*)(ExtInfo
->Mapping
), s
, (int8
**)&(ExtInfo
->Mapping
), 2*sizeof(EXTENT_MAP
))) {
2581 // This must never happen on truncate !!!
2582 AdPrint(("ResizeExtent: MyReallocPool__(9) failed\n"));
2584 ExtInfo
->Mapping
[0].extLength
= LBS
| (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2585 ExtInfo
->Mapping
[0].extLocation
=
2586 ExtInfo
->Mapping
[1].extLength
=
2587 ExtInfo
->Mapping
[1].extLocation
= 0;
2589 if(ExtInfo
->Offset
) {
2591 // remove 1st entry pointing to FileEntry
2592 s
= UDFGetMappingLength(ExtInfo
->Mapping
);
2593 RtlMoveMemory(&(ExtInfo
->Mapping
[0]), &(ExtInfo
->Mapping
[1]), s
- sizeof(EXTENT_MAP
));
2594 if(!MyReallocPool__((int8
*)(ExtInfo
->Mapping
), s
,
2595 (int8
**)&(ExtInfo
->Mapping
), s
- sizeof(EXTENT_MAP
) )) {
2596 // This must never happen on truncate !!!
2597 AdPrint(("ResizeExtent: MyReallocPool__(10) failed\n"));
2599 Length
-= ExtInfo
->Offset
;
2600 ExtInfo
->Offset
= 0;
2602 Length
-= ExtInfo
->Offset
; // back to in-icb
2605 ExtInfo
->Length
= Length
;
2606 UDFCheckSpaceAllocation(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // check if used
2608 for(i
=0; (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
); i
++) {
2609 ExtPrint(("Resized Ext: type %x, loc %x, len %x\n",
2610 ExtInfo
->Mapping
[i
].extLength
>> 30, ExtInfo
->Mapping
[i
].extLocation
, ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
));
2613 return STATUS_SUCCESS
;
2614 } // end UDFResizeExtent()
2617 This routine (re)builds AllocDescs data for all allocation modes except
2618 in-ICB & resizes associated extent (FileInfo->Dloc->AllocLoc) for
2619 already allocated user data extent (FileInfo->Dloc->DataLoc).
2620 AllocMode in FileEntry pointed by FileInfo must be already initialized.
2626 IN OUT PUDF_FILE_INFO FileInfo
,
2627 OUT int8
** AllocData
2630 // PEXTENT_MAP InMap;
2637 ValidateFileInfo(FileInfo
);
2638 AdPrint(("BuildAllocDesc\n"));
2639 // get space available in the 1st LBlock after FE
2640 InitSz
= Vcb
->LBlockSize
- FileInfo
->Dloc
->FileEntryLen
;
2641 Allocs
= (int8
*)MyAllocatePool__(NonPagedPool
, InitSz
);
2643 AdPrint(("BuildAllocDesc: cant alloc %x bytes for Allocs\n", InitSz
));
2644 return STATUS_INSUFFICIENT_RESOURCES
;
2646 RtlZeroMemory(Allocs
, InitSz
);
2647 // InMap = FileInfo->Dloc->DataLoc.Mapping;
2648 UDFCheckSpaceAllocation(Vcb
, 0, InMap
, AS_USED
); // check if used
2650 // TODO: move data from mapped locations here
2652 AllocMode
= ((PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->icbTag
.flags
& ICB_FLAG_ALLOC_MASK
;
2654 case ICB_FLAG_AD_IN_ICB
: {
2655 MyFreePool__(Allocs
);
2656 ASSERT(!FileInfo
->Dloc
->AllocLoc
.Mapping
);
2658 status
= STATUS_SUCCESS
;
2661 case ICB_FLAG_AD_SHORT
: {
2662 status
= UDFBuildShortAllocDescs(Vcb
, PartNum
, &Allocs
, InitSz
, FileInfo
);
2665 case ICB_FLAG_AD_LONG
: {
2666 status
= UDFBuildLongAllocDescs(Vcb
, PartNum
, &Allocs
, InitSz
, FileInfo
);
2669 /* case ICB_FLAG_AD_EXTENDED: {
2670 status = UDFBuildExtAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo);
2674 MyFreePool__(Allocs
);
2676 status
= STATUS_INVALID_PARAMETER
;
2680 *AllocData
= Allocs
;
2681 UDFCheckSpaceAllocation(Vcb
, 0, FileInfo
->Dloc
->DataLoc
.Mapping
, AS_USED
); // check if used
2684 } // end UDFBuildAllocDescs()
2687 This routine discards file's allocation
2690 UDFFreeFileAllocation(
2692 IN PUDF_FILE_INFO DirInfo
,
2693 IN PUDF_FILE_INFO FileInfo
2696 if(FileInfo
->Dloc
->DataLoc
.Offset
) {
2698 if(FileInfo
->Dloc
->DataLoc
.Mapping
) {
2699 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
==
2700 FileInfo
->Dloc
->DataLoc
.Mapping
[0].extLocation
);
2701 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, &(FileInfo
->Dloc
->DataLoc
.Mapping
[1]), AS_DISCARDED
); // free
2702 FileInfo
->Dloc
->DataLoc
.Mapping
[1].extLocation
=
2703 FileInfo
->Dloc
->DataLoc
.Mapping
[1].extLength
= 0;
2704 FileInfo
->Dloc
->DataLoc
.Mapping
[0].extLocation
= 0;
2705 FileInfo
->Dloc
->DataLoc
.Mapping
[0].extLength
= EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30;
2707 if(FileInfo
->Dloc
->AllocLoc
.Mapping
) {
2708 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
==
2709 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
);
2710 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, &(FileInfo
->Dloc
->AllocLoc
.Mapping
[1]), AS_DISCARDED
); // free
2711 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLocation
=
2712 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLength
= 0;
2713 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
= 0;
2714 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLength
= EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30;
2716 UDFFreeFESpace(Vcb
, DirInfo
, &(FileInfo
->Dloc
->FELoc
));
2718 if(FileInfo
->Dloc
->AllocLoc
.Mapping
) {
2719 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
==
2720 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
);
2721 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, &(FileInfo
->Dloc
->AllocLoc
.Mapping
[1]), AS_DISCARDED
); // free
2722 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLocation
=
2723 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLength
= 0;
2724 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
= 0;
2725 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLength
= EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30;
2727 UDFFreeFESpace(Vcb
, DirInfo
, &(FileInfo
->Dloc
->FELoc
));
2728 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, FileInfo
->Dloc
->DataLoc
.Mapping
, AS_DISCARDED
); // free
2730 FileInfo
->Dloc
->DataLoc
.Modified
=
2731 FileInfo
->Dloc
->AllocLoc
.Modified
=
2732 FileInfo
->Dloc
->FELoc
.Modified
= FALSE
;
2733 } // end UDFFreeFileAllocation()
2734 #endif //UDF_READ_ONLY_BUILD
2737 This routine packs physically sequential extents into single one
2743 IN PEXTENT_INFO ExtInfo
// Extent array
2746 PEXTENT_MAP NewMap
, OldMap
;
2748 uint32 LastLba
, LastType
, OldLen
;
2749 uint32 OldSize
, NewSize
;
2754 AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
2755 AdPrint((" Length %x\n", ExtInfo
->Length
));
2757 OldMap
= ExtInfo
->Mapping
;
2758 LastLba
= OldMap
[0].extLocation
;
2759 OldLen
= (OldMap
[0].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
;
2760 LastType
= OldMap
[0].extLength
>> 30;
2762 NewSize
= UDFGetMappingLength(OldMap
);
2764 check_size
= UDFGetExtentLength(ExtInfo
->Mapping
);
2765 ASSERT(!(check_size
& (2048-1)));
2768 l
=OldMap
[0].extLength
& UDF_EXTENT_LENGTH_MASK
;
2769 // calculate required length
2770 for(i
=1; OldMap
[i
].extLength
; i
++) {
2771 if((LastType
== (OldMap
[i
].extLength
>> 30))
2773 ((OldMap
[i
].extLocation
== LastLba
+ OldLen
) ||
2774 (!OldMap
[i
].extLocation
&& !LastLba
&& (LastType
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
)))
2776 (l
+ (OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) <= UDF_MAX_EXTENT_LENGTH
)) {
2777 // we can pack two blocks in one
2778 l
+= OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2779 NewSize
-= sizeof(EXTENT_MAP
);
2781 l
= OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2783 LastLba
= OldMap
[i
].extLocation
;
2784 LastType
= OldMap
[i
].extLength
>> 30;
2785 OldLen
= (OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
;
2788 if(OldSize
<= (NewSize
+ PACK_MAPPING_THRESHOLD
)) {
2789 if(OldSize
== NewSize
)
2791 if(NewSize
>= PACK_MAPPING_THRESHOLD
)
2794 AdPrint(("Pack ExtInfo %x, Mapping %x, realloc\n", ExtInfo
, ExtInfo
->Mapping
));
2795 NewMap
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, NewSize
,