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
));
1863 ASSERT(check_size
== UDFGetExtentLength(ExtInfo
->Mapping
));
1864 AdPrint(("Alloc->Rec: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
1865 return STATUS_SUCCESS
;
1867 if(Extent
[i
].extLocation
< lba
) {
1868 if( (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) - (lba
- Extent
[i
].extLocation
))
1871 NewExtent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
)*2,
1873 if(!NewExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
1874 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1875 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
1876 RtlCopyMemory((int8
*)&(NewExtent
[i
+3]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
1877 NewExtent
[i
].extLocation
= Extent
[i
].extLocation
;
1878 NewExtent
[i
].extLength
= (lba
- Extent
[i
].extLocation
) << BSh
;
1879 NewExtent
[i
+1].extLength
= (Length
+BS
-1) & ~(BS
-1);
1880 NewExtent
[i
+1].extLocation
= lba
;
1881 NewExtent
[i
+2].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
- NewExtent
[i
+1].extLength
;
1882 NewExtent
[i
+2].extLocation
= lba
+ ((Length
+BS
-1) >> BSh
);
1883 ASSERT(!(NewExtent
[i
].extLength
>> 30));
1884 ASSERT(!(NewExtent
[i
+2].extLength
>> 30));
1885 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1886 NewExtent
[i
+2].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1888 AdPrint(("Alloc->Rec (2) new %x\n", NewExtent
));
1891 NewExtent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
),
1893 if(!NewExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
1894 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1895 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
1896 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
1897 NewExtent
[i
].extLocation
= Extent
[i
].extLocation
;
1898 NewExtent
[i
].extLength
= (lba
- Extent
[i
].extLocation
) << BSh
;
1899 NewExtent
[i
+1].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
;
1900 NewExtent
[i
+1].extLocation
= lba
;
1901 ASSERT(!(NewExtent
[i
].extLength
>> 30));
1902 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1903 AdPrint(("Alloc->Rec (3) new %x\n", NewExtent
));
1907 NewExtent
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
),
1909 if(!NewExtent
) return STATUS_INSUFFICIENT_RESOURCES
;
1910 Extent
[i
].extLength
&= UDF_EXTENT_LENGTH_MASK
;
1911 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
1912 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
1913 NewExtent
[i
].extLocation
= Extent
[i
].extLocation
;
1914 NewExtent
[i
].extLength
= (Length
+BS
-1) & ~(BS
-1);
1915 NewExtent
[i
+1].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
;
1916 NewExtent
[i
+1].extLocation
= Extent
[i
].extLocation
+ (NewExtent
[i
].extLength
>> BSh
);
1917 ASSERT(!(NewExtent
[i
+1].extLength
>> 30));
1918 NewExtent
[i
+1].extLength
|= (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
1919 AdPrint(("Alloc->Rec (4) new %x\n", NewExtent
));
1922 //ASSERT(check_size == UDFGetExtentLength(Extent));
1923 //ASSERT(!(check_size & (LBS-1)));
1925 AdPrint(("Free Extent %x (new %x)\n", Extent
, NewExtent
));
1926 MyFreePool__(Extent
);
1927 ExtInfo
->Modified
= TRUE
;
1928 ExtInfo
->Mapping
= NewExtent
;
1930 UDFPackMapping(Vcb
, ExtInfo
);
1931 ASSERT(check_size
== UDFGetExtentLength(ExtInfo
->Mapping
));
1932 ASSERT(!(check_size
& (LBS
-1)));
1934 AdPrint(("Alloc->Rec: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
1936 return STATUS_SUCCESS
;
1937 } // end UDFMarkAllocatedAsRecorded()
1940 This routine rebuilds mapping on write attempts to Not-Alloc-Not-Rec area.
1941 Here we assume that required area lays in a single frag.
1944 UDFMarkNotAllocatedAsAllocated(
1948 IN PEXTENT_INFO ExtInfo
// Extent array
1951 uint32 i
, len
, /*lba,*/ d
, l
, BOffs
, j
;
1952 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
1953 PEXTENT_MAP NewExtent
;
1954 // uint32 BS = Vcb->BlockSize;
1955 uint32 BSh
= Vcb
->BlockSizeBits
;
1957 EXTENT_INFO TmpExtInf
;
1959 uint32 LBS
= Vcb
->LBlockSize
;
1960 // I don't know what else comment can be added here.
1961 // Just belive that it works
1963 #ifndef ALLOW_SPARSE
1966 AdPrint(("Not->Alloc ExtInfo %x, Extent %x\n", ExtInfo
, Extent
));
1967 UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Offset
, NULL
, NULL
, NULL
, &i
);
1968 if(i
== (ULONG
)-1) return STATUS_INVALID_PARAMETER
;
1969 if((Extent
[i
].extLength
>> 30) != EXTENT_NOT_RECORDED_NOT_ALLOCATED
) return STATUS_SUCCESS
;
1971 uint32 PartNum
= UDFGetPartNumByPhysLba(Vcb
, Extent
[0].extLocation
);
1972 BOffs
= (uint32
)(Offset
>> BSh
);
1973 // length of existing Not-Alloc-Not-Rec frag
1974 sLen
= (( (((uint32
)Offset
) & (LBS
-1)) + Length
+LBS
-1) & ~(LBS
-1)) >> BSh
;
1975 // required allocation length increment (in bytes)
1976 aLen
= (uint32
)( ((Offset
+Length
+LBS
-1) & ~(LBS
-1)) - (Offset
& ~(LBS
-1)));
1978 // try to extend previous frag or allocate space _after_ it to
1979 // avoid backward seeks, if previous frag is not Not-Rec-Not-Alloc
1980 if(i
&& ((Extent
[i
-1].extLength
>> 30) != EXTENT_NOT_RECORDED_NOT_ALLOCATED
) ) {
1981 status
= UDFAllocFreeExtent(Vcb
, aLen
,
1982 Extent
[i
-1].extLocation
+ ((Extent
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
),
1983 min(UDFPartEnd(Vcb
, PartNum
), Extent
[i
-1].extLocation
+ ((Extent
[i
-1].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) + sLen
),
1984 &TmpExtInf
, ExtInfo
->Flags
/*& EXTENT_FLAG_ALLOC_MASK*/);
1985 if(status
== STATUS_DISK_FULL
)
1986 // if there are not enough free blocks after that frag...
1987 goto try_alloc_anywhere
;
1990 // ... try to alloc required disk space anywhere
1991 status
= UDFAllocFreeExtent(Vcb
, aLen
,
1992 UDFPartStart(Vcb
, PartNum
),
1993 UDFPartEnd(Vcb
, PartNum
),
1994 &TmpExtInf
, ExtInfo
->Flags
/*& EXTENT_FLAG_ALLOC_MASK*/);
1996 // check for successfull allocation
1997 if(!OS_SUCCESS(status
)) {
1998 AdPrint(("Not->Alloc no free\n"));
2001 // get number of frags in allocated block
2002 d
= (UDFGetMappingLength(TmpExtInf
.Mapping
) / sizeof(EXTENT_MAP
)) - 1;
2003 // calculate number of existing blocks before the frag to be changed
2005 for(j
=0; j
<i
; j
++) {
2006 l
+= (uint32
)((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2008 // and now just update mapping...
2009 if( (l
== BOffs
) && (((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) == sLen
) ) {
2011 // (d-1) - since we have to raplace last frag of Extent with 1 or more frags of TmpExtInf.Mapping
2012 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + (d
-1)*sizeof(EXTENT_MAP
) );
2014 MyFreePool__(TmpExtInf
.Mapping
);
2015 return STATUS_INSUFFICIENT_RESOURCES
;
2017 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2018 RtlCopyMemory((int8
*)&(NewExtent
[i
]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2019 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2020 AdPrint(("Not->Alloc (1) new %x\n", NewExtent
));
2023 // .ExtLength, BOffs & l are already aligned...
2024 if( (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) - (BOffs
-l
)) > sLen
) {
2026 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + (d
+1)*sizeof(EXTENT_MAP
) );
2028 MyFreePool__(TmpExtInf
.Mapping
);
2029 return STATUS_INSUFFICIENT_RESOURCES
;
2031 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2032 RtlCopyMemory((int8
*)&(NewExtent
[i
+1]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2033 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2034 NewExtent
[i
].extLocation
= 0;
2035 NewExtent
[i
].extLength
= (BOffs
- l
) << BSh
;
2036 NewExtent
[i
+d
+1].extLength
= Extent
[i
].extLength
- NewExtent
[i
].extLength
- aLen
;
2037 NewExtent
[i
+d
+1].extLocation
= 0;
2038 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2039 NewExtent
[i
+d
+1].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2040 AdPrint(("Not->Alloc (2) new %x\n", NewExtent
));
2043 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + d
*sizeof(EXTENT_MAP
) );
2045 MyFreePool__(TmpExtInf
.Mapping
);
2046 return STATUS_INSUFFICIENT_RESOURCES
;
2048 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2049 RtlCopyMemory((int8
*)&(NewExtent
[i
+1]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2050 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
+1]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2051 NewExtent
[i
].extLocation
= 0;
2052 NewExtent
[i
].extLength
= (BOffs
- l
) << BSh
;
2053 NewExtent
[i
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2054 AdPrint(("Not->Alloc (3) new %x\n", NewExtent
));
2058 NewExtent
= (PEXTENT_AD
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + d
*sizeof(EXTENT_MAP
) );
2060 MyFreePool__(TmpExtInf
.Mapping
);
2061 return STATUS_INSUFFICIENT_RESOURCES
;
2063 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2064 RtlCopyMemory((int8
*)&(NewExtent
[i
]), (int8
*)(TmpExtInf
.Mapping
), d
*sizeof(EXTENT_MAP
) );
2065 RtlCopyMemory((int8
*)&(NewExtent
[i
+d
+1]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2066 NewExtent
[i
+d
].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) - aLen
;
2067 NewExtent
[i
+d
].extLocation
= 0;
2068 NewExtent
[i
+d
].extLength
|= (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2069 AdPrint(("Not->Alloc (4) new %x\n", NewExtent
));
2072 AdPrint(("Free Extent %x, TmpExtInf.Mapping, (new %x)\n", Extent
, TmpExtInf
.Mapping
, NewExtent
));
2073 MyFreePool__(Extent
);
2074 MyFreePool__(TmpExtInf
.Mapping
);
2075 ExtInfo
->Modified
= TRUE
;
2076 ExtInfo
->Mapping
= NewExtent
;
2078 AdPrint(("Not->Alloc: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
2080 return STATUS_SUCCESS
;
2081 } // end UDFMarkNotAllocatedAsAllocated()
2085 This routine rebuilds mapping on write zero attempts to
2087 Here we assume that required area lays in a single frag.
2090 UDFMarkAllocatedAsNotXXX(
2094 IN PEXTENT_INFO ExtInfo
, // Extent array
2095 IN BOOLEAN Deallocate
2098 uint32 i
, len
, /*lba, d,*/ l
, BOffs
, j
;
2099 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
2100 PEXTENT_MAP NewExtent
;
2101 // EXTENT_MAP TmpExtent;
2102 // uint32 BS = Vcb->BlockSize;
2103 uint32 BSh
= Vcb
->BlockSizeBits
;
2105 EXTENT_INFO TmpExtInf
;
2108 uint32 target_flags
= Deallocate
?
2109 EXTENT_NOT_RECORDED_NOT_ALLOCATED
:
2110 EXTENT_NOT_RECORDED_ALLOCATED
;
2111 uint32 LBS
= Vcb
->LBlockSize
;
2112 EXTENT_MAP DeadMapping
[2];
2113 // I don't know what else comment can be added here.
2114 // Just belive that it works
2116 #ifndef ALLOW_SPARSE
2122 AdPrint(("Alloc->Not ExtInfo %x, Extent %x\n", ExtInfo
, Extent
));
2124 DeadMapping
[0].extLocation
=
2125 UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Offset
, NULL
, NULL
, NULL
, &i
);
2126 if(i
== (ULONG
)-1) {
2128 return STATUS_INVALID_PARAMETER
;
2130 DeadMapping
[0].extLength
= Extent
[i
].extLength
;
2131 DeadMapping
[1].extLocation
=
2132 DeadMapping
[1].extLength
= 0;
2133 TmpExtInf
.Mapping
= (PEXTENT_MAP
)&DeadMapping
;
2134 TmpExtInf
.Offset
= 0;
2135 TmpExtInf
.Length
= Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2137 flags
= Extent
[i
].extLength
>> 30;
2138 if(flags
== target_flags
) return STATUS_SUCCESS
;
2140 // uint32 PartNum = UDFGetPartNumByPhysLba(Vcb, Extent[0].extLocation);
2141 BOffs
= (uint32
)(Offset
>> BSh
);
2142 // length of existing Alloc-(Not-)Rec frag (in sectors)
2143 sLen
= (( (((uint32
)Offset
) & (LBS
-1)) + Length
+LBS
-1) & ~(LBS
-1)) >> BSh
;
2144 // required deallocation length increment (in bytes)
2145 aLen
= (uint32
)( ((Offset
+Length
+LBS
-1) & ~(LBS
-1)) - (Offset
& ~(LBS
-1)) );
2148 for(j
=0; j
<i
; j
++) {
2149 l
+= (uint32
)((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2152 if( (l
== BOffs
) && (((Extent
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) == sLen
) ) {
2154 Extent
[i
].extLocation
= 0;
2155 Extent
[i
].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) | flags
;
2157 AdPrint(("Alloc->Not (1) NewExtent = Extent = %x\n", NewExtent
));
2160 // .ExtLength, BOffs & l are already aligned...
2161 if( (((Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
) - (BOffs
-l
)) > sLen
) {
2163 NewExtent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + 2*sizeof(EXTENT_MAP
) );
2165 return STATUS_INSUFFICIENT_RESOURCES
;
2167 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2168 RtlCopyMemory((int8
*)&(NewExtent
[i
+3]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2169 NewExtent
[i
].extLength
= (BOffs
- l
) << BSh
;
2170 NewExtent
[i
].extLength
|= flags
;
2171 NewExtent
[i
+1].extLocation
= 0;
2172 NewExtent
[i
+1].extLength
= aLen
| (target_flags
<< 30);
2173 NewExtent
[i
+2].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) -
2174 (NewExtent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) - aLen
;
2175 NewExtent
[i
+2].extLocation
= Extent
[i
].extLocation
+
2176 (NewExtent
[i
+2].extLength
>> BSh
);
2177 NewExtent
[i
+2].extLength
|= flags
;
2178 AdPrint(("Alloc->Not (2) new %x\n", NewExtent
));
2181 NewExtent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
) );
2183 return STATUS_INSUFFICIENT_RESOURCES
;
2185 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2186 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2187 NewExtent
[i
].extLength
= ((BOffs
- l
) << BSh
) | flags
;
2188 NewExtent
[i
+1].extLocation
= 0;
2189 NewExtent
[i
+1].extLength
= aLen
| (target_flags
<< 30);
2190 AdPrint(("Alloc->Not (3) new %x\n", NewExtent
));
2194 NewExtent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, UDFGetMappingLength(Extent
) + sizeof(EXTENT_MAP
) );
2196 return STATUS_INSUFFICIENT_RESOURCES
;
2198 RtlCopyMemory((int8
*)NewExtent
, (int8
*)Extent
, i
*sizeof(EXTENT_MAP
));
2199 RtlCopyMemory((int8
*)&(NewExtent
[i
+2]), (int8
*)&(Extent
[i
+1]), len
= UDFGetMappingLength(&(Extent
[i
+1])) );
2200 NewExtent
[i
+1].extLength
= (Extent
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) - aLen
;
2201 NewExtent
[i
+1].extLength
|= flags
;
2202 NewExtent
[i
].extLocation
= 0;
2203 NewExtent
[i
].extLength
= aLen
| (target_flags
<< 30);
2204 AdPrint(("Alloc->Not (4) new %x\n", NewExtent
));
2208 UDFMarkSpaceAsXXX(Vcb
, (-1), TmpExtInf
.Mapping
, AS_DISCARDED
); // mark as free
2211 AdPrint(("Alloc->Not kill %x\n", Extent
));
2212 MyFreePool__(Extent
);
2214 AdPrint(("Alloc->Not keep %x\n", Extent
));
2216 ExtInfo
->Modified
= TRUE
;
2217 ExtInfo
->Mapping
= NewExtent
;
2218 AdPrint(("Alloc->Not: ExtInfo %x, Extent %x\n", ExtInfo
, ExtInfo
->Mapping
));
2220 return STATUS_SUCCESS
;
2221 } // end UDFMarkAllocatedAsNotXXX()
2225 This routine resizes extent & updates associated mapping
2231 IN int64 Length
, // Required Length
2232 IN BOOLEAN AlwaysInIcb
, // must be TRUE for AllocDescs
2233 OUT PEXTENT_INFO ExtInfo
2236 uint32 i
, flags
, lba
, lim
;
2239 EXTENT_INFO TmpExtInf
;
2240 EXTENT_MAP TmpMapping
[2];
2241 uint32 s
, req_s
, pe
, BSh
, LBS
, PS
;
2242 LBS
= Vcb
->LBlockSize
;
2243 BSh
= Vcb
->BlockSizeBits
;
2244 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
2245 uint32 MaxGrow
= (UDF_MAX_EXTENT_LENGTH
& ~(LBS
-1));
2246 BOOLEAN Sequential
= FALSE
;
2248 ASSERT(PartNum
< 3);
2250 ExtPrint(("Resize ExtInfo %x, %I64x -> %I64x\n", ExtInfo
, ExtInfo
->Length
, Length
));
2252 if(ExtInfo
->Flags
& EXTENT_FLAG_CUT_PREALLOCATED
) {
2253 AdPrint((" cut preallocated\n"));
2255 if(ExtInfo
->Length
== Length
) {
2256 return STATUS_SUCCESS
;
2258 if((ExtInfo
->Flags
& EXTENT_FLAG_ALLOC_MASK
) == EXTENT_FLAG_ALLOC_SEQUENTIAL
) {
2259 MaxGrow
&= ~(Vcb
->WriteBlockSize
-1);
2263 UDFCheckSpaceAllocation(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // check if used
2264 if(ExtInfo
->Offset
) {
2265 if(ExtInfo
->Offset
+ Length
<= LBS
) {
2266 ExtPrint(("Resize IN-ICB\n"));
2267 ExtInfo
->Length
= Length
;
2268 return STATUS_SUCCESS
;
2270 if(!AlwaysInIcb
) // simulate unused 1st sector in extent
2271 ExtInfo
->Offset
= LBS
; // it'll be truncated later
2272 Length
+= ExtInfo
->Offset
; // convert to real offset in extent
2274 lba
= UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Length
, NULL
, NULL
, &flags
, &i
);
2275 if(ExtInfo
->Length
< Length
) {
2277 if(OS_SUCCESS(UDFGetCachedAllocation(Vcb
, ExtInfo
->Mapping
[0].extLocation
,
2278 &TmpExtInf
, NULL
, UDF_PREALLOC_CLASS_DIR
))) {
2279 AdPrint(("Resize found cached(1)\n"));
2280 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, TmpExtInf
.Mapping
);
2281 MyFreePool__(TmpExtInf
.Mapping
);
2283 if((l
= UDFGetExtentLength(ExtInfo
->Mapping
)) >= Length
) {
2284 // we have enough space inside extent
2285 ExtInfo
->Length
= Length
;
2286 AdPrint(("Resize do nothing (1)\n"));
2287 } else /*if(lba == LBA_OUT_OF_EXTENT)*/ {
2289 Length
-= ExtInfo
->Offset
;
2290 if(/*Length && l &&*/ (l
% MaxGrow
) &&
2291 (Length
-1)/MaxGrow
!= (l
-1)/MaxGrow
) {
2292 AdPrint(("Crossing MAX_FRAG boundary...\n"));
2293 int64 l2
= ((l
-1)/MaxGrow
+ 1)*MaxGrow
;
2294 status
= UDFResizeExtent(Vcb
, PartNum
, l2
, AlwaysInIcb
, ExtInfo
);
2295 if(!OS_SUCCESS(status
)) {
2296 KdPrint(("Sub-call to UDFResizeExtent() failed (%x)\n", status
));
2299 l
= ExtInfo
->Length
;
2302 while((Length
- l
) > MaxGrow
) {
2303 status
= UDFResizeExtent(Vcb
, PartNum
, l
+MaxGrow
, AlwaysInIcb
, ExtInfo
);
2304 if(!OS_SUCCESS(status
)) {
2305 KdPrint(("Sub-call (2) to UDFResizeExtent() failed (%x)\n", status
));
2308 l
= ExtInfo
->Length
;
2310 Length
+= ExtInfo
->Offset
;
2311 // at first, try to resize existing frag
2312 #ifndef UDF_ALLOW_FRAG_AD
2313 i
= UDFGetMappingLength(ExtInfo
->Mapping
);
2314 if(i
> (LBS
-sizeof(EXTENDED_FILE_ENTRY
))) {
2315 // this is very important check since we will not
2316 // be able to _record_ too long AllocDesc because of
2317 // some DEMO limitations in UDFBuildXXXAllocDescs()
2318 AdPrint((" DISK_FULL\n"));
2319 return STATUS_DISK_FULL
;
2321 i
/= sizeof(EXTENT_MAP
);
2322 #else //UDF_ALLOW_FRAG_AD
2323 i
= UDFGetMappingLength(ExtInfo
->Mapping
) / sizeof(EXTENT_MAP
);
2324 #endif //UDF_ALLOW_FRAG_AD
2326 if(!AlwaysInIcb
&& !(ExtInfo
->Offset
) &&
2327 (Length
- l
>= (Vcb
->SparseThreshold
<< BSh
))) {
2328 // last frag will be Not-Alloc-Not-Rec...
2329 AdPrint(("Resize sparse (2)\n"));
2330 RtlZeroMemory(&TmpExtInf
, sizeof(EXTENT_INFO
));
2331 TmpExtInf
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, sizeof(EXTENT_MAP
)*2,
2333 if(!TmpExtInf
.Mapping
) return STATUS_INSUFFICIENT_RESOURCES
;
2334 TmpExtInf
.Mapping
[0].extLength
= (((uint32
)(Length
- l
) + LBS
-1) & ~(LBS
-1)) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2335 TmpExtInf
.Mapping
[0].extLocation
=// 0;
2336 TmpExtInf
.Mapping
[1].extLength
=
2337 TmpExtInf
.Mapping
[1].extLocation
= 0;
2339 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, TmpExtInf
.Mapping
);
2340 MyFreePool__(TmpExtInf
.Mapping
);
2342 #endif //ALLOW_SPARSE
2343 // allocate some sectors
2344 if(i
>1 && !(ExtInfo
->Offset
)) {
2346 // check if Not-Alloc-Not-Rec at the end of mapping
2347 if((uint32
)Length
- (uint32
)l
+ (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) > MaxGrow
) {
2348 // do nothing, but jump directly to allocator
2350 if((ExtInfo
->Mapping
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
2351 AdPrint(("Resize grow sparse (3)\n"));
2352 ExtInfo
->Mapping
[i
].extLength
+=
2353 (((uint32
)Length
-(uint32
)l
+LBS
-1) & ~(LBS
-1)) ;
2355 // check if Alloc-Not-Rec at the end of mapping
2356 } else if((ExtInfo
->Mapping
[i
].extLength
>> 30) == EXTENT_NOT_RECORDED_ALLOCATED
) {
2357 AdPrint(("Resize grow Not-Rec (3)\n"));
2358 // current length of last frag
2359 s
= ((ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2360 // prefered location of the next frag
2361 lba
= ExtInfo
->Mapping
[i
].extLocation
+ s
;
2362 pe
=UDFPartEnd(Vcb
,PartNum
);
2363 // maximum frag length
2365 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(PS
-1);
2367 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(LBS
-1);
2369 // required last extent length
2370 req_s
= s
+ (uint32
)( (((Length
+ LBS
- 1) & ~(LBS
-1)) -
2371 ((l
+ LBS
- 1) & ~(LBS
-1)) ) >> BSh
);
2375 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
2376 /* if((ExtInfo->Flags & EXTENT_FLAG_SEQUENTIAL) &&
2377 ((Length & ~(PS-1)) > (l & ~(PS-1))) &&
2379 status = UDFResizeExtent(Vcb, PartNum, l+MaxGrow, AlwaysInIcb, ExtInfo);
2381 // how many sectors we should add
2384 if((lba
< pe
) && UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
)) {
2385 s
+= UDFGetBitmapLen((uint32
*)(Vcb
->FSBM_Bitmap
), lba
, min(pe
, lba
+req_s
-1));
2387 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) {
2391 // we can just increase the last frag
2392 AdPrint(("Resize grow last Not-Rec (4)\n"));
2393 ExtInfo
->Mapping
[i
].extLength
= (lim
<< BSh
) | (EXTENT_NOT_RECORDED_ALLOCATED
<< 30);
2395 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_USED
); // mark as used
2397 // we get here if simple increasing of last frag failed
2398 // it worth truncating last frag and try to allocate
2399 // all required data as a single frag
2401 /* if(Sequential && s>=PS) {
2403 AdPrint(("Resize grow last Not-Rec (4/2)\n"));
2404 ExtInfo->Mapping[i].extLength = (s << BSh) | (EXTENT_NOT_RECORDED_ALLOCATED << 30);
2406 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // mark as used
2408 AdPrint(("Resize reloc last Not-Rec (5)\n"));
2409 TmpExtInf
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, (i
+1)*sizeof(EXTENT_MAP
),
2411 if(!TmpExtInf
.Mapping
) {
2412 KdPrint(("UDFResizeExtent: !TmpExtInf.Mapping\n"));
2413 UDFReleaseResource(&(Vcb
->BitMapResource1
));
2414 return STATUS_INSUFFICIENT_RESOURCES
;
2416 RtlCopyMemory(TmpExtInf
.Mapping
, ExtInfo
->Mapping
, i
*sizeof(EXTENT_MAP
));
2417 TmpExtInf
.Mapping
[i
].extLength
=
2418 TmpExtInf
.Mapping
[i
].extLocation
= 0;
2419 TmpExtInf
.Offset
= ExtInfo
->Offset
;
2420 l
-= (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
);
2421 TmpExtInf
.Length
= l
;
2422 ASSERT(i
|| !ExtInfo
->Offset
);
2423 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_DISCARDED
); // mark as free
2424 MyFreePool__(ExtInfo
->Mapping
);
2425 (*ExtInfo
) = TmpExtInf
;
2427 UDFCheckSpaceAllocation(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // check if used
2428 UDFReleaseResource(&(Vcb
->BitMapResource1
));
2429 // check if Alloc-Rec
2431 // current length of last frag
2432 s
= ((ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> BSh
);
2433 // prefered location of the next frag
2434 lba
= ExtInfo
->Mapping
[i
].extLocation
+ s
;
2435 pe
=UDFPartEnd(Vcb
,PartNum
);
2436 // maximum frag length
2438 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(PS
-1);
2440 lim
= (((uint32
)UDF_MAX_EXTENT_LENGTH
) >> BSh
) & ~(LBS
-1);
2442 // required last extent length
2443 req_s
= s
+ (uint32
)( (((Length
+ LBS
- 1) & ~(LBS
-1)) -
2444 ((l
+ LBS
- 1) & ~(LBS
-1)) ) >> BSh
);
2449 // how many sectors we should add
2454 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
2456 if((lba
< pe
) && UDFGetFreeBit(Vcb
->FSBM_Bitmap
, lba
)) {
2457 s
+= (d
= UDFGetBitmapLen((uint32
*)(Vcb
->FSBM_Bitmap
), lba
, min(pe
, lba
+req_s
-1)));
2459 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) {
2464 AdPrint(("Resize grow last Rec (6)\n"));
2465 // we can just increase last frag
2466 TmpMapping
[0].extLength
= req_s
<< BSh
;
2467 TmpMapping
[0].extLocation
= lba
;
2468 TmpMapping
[1].extLength
=
2469 TmpMapping
[1].extLocation
= 0;
2470 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &TmpMapping
[0], AS_USED
); // mark as used
2471 l
+= (s
<< BSh
) - (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
);
2472 ExtInfo
->Mapping
[i
].extLength
= (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_FLAG_MASK
) | (s
<< BSh
);
2474 AdPrint(("Resize part-grow last Rec (6)\n"));
2475 // increase last frag, then alloc rest
2476 TmpMapping
[0].extLength
= d
<< BSh
;
2477 TmpMapping
[0].extLocation
= lba
;
2478 TmpMapping
[1].extLength
=
2479 TmpMapping
[1].extLocation
= 0;
2480 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &TmpMapping
[0], AS_USED
); // mark as used
2481 l
+= (s
<< BSh
) - (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
);
2482 ExtInfo
->Mapping
[i
].extLength
= (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_FLAG_MASK
) | (s
<< BSh
);
2484 AdPrint(("Can't grow last Rec (6)\n"));
2486 UDFReleaseResource(&(Vcb
->BitMapResource1
));
2488 AdPrint(("Max frag length reached (6)\n"));
2493 // we get here if simple increasing of the last frag failed
2494 AdPrint(("Resize add new frag (7)\n"));
2495 if(l
< LBS
&& Length
>= LBS
&&
2496 (ExtInfo
->Flags
& EXTENT_FLAG_ALLOC_MASK
) == EXTENT_FLAG_ALLOC_SEQUENTIAL
) {
2497 AdPrint(("Resize tune for SEQUENTIAL i/o\n"));
2499 status
= UDFAllocFreeExtent(Vcb
, Length
- l
,
2500 UDFPartStart(Vcb
, PartNum
),
2501 UDFPartEnd(Vcb
, PartNum
),
2503 ExtInfo
->Flags
/*& EXTENT_FLAG_ALLOC_MASK*/);
2504 if(!OS_SUCCESS(status
)) {
2505 KdPrint(("UDFResizeExtent: UDFAllocFreeExtent() failed (%x)\n", status
));
2508 ExtInfo
->Mapping
= UDFMergeMappings(ExtInfo
->Mapping
, TmpExtInf
.Mapping
);
2509 MyFreePool__(TmpExtInf
.Mapping
);
2511 UDFPackMapping(Vcb
, ExtInfo
);
2516 AdPrint(("Resize cut (8)\n"));
2517 lba
= UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Length
-1, NULL
, &lim
, &flags
, &i
);
2519 ASSERT(lba
!= LBA_OUT_OF_EXTENT
);
2520 ASSERT(lba
!= LBA_NOT_ALLOCATED
);
2522 if(ExtInfo
->Mapping
[i
].extLength
) {
2523 UDFCheckSpaceAllocation(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_USED
); // check if used
2524 if(!ExtInfo
->Offset
&& (ExtInfo
->Flags
& EXTENT_FLAG_PREALLOCATED
)) {
2526 AdPrint(("Resize try save cutted (8)\n"));
2527 RtlZeroMemory(&TmpExtInf
, sizeof(EXTENT_INFO
));
2528 s
= UDFGetMappingLength(&(ExtInfo
->Mapping
[i
]));
2530 TmpExtInf
.Mapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, s
, MEM_EXTMAP_TAG
);
2531 if(TmpExtInf
.Mapping
) {
2532 RtlCopyMemory(TmpExtInf
.Mapping
, &(ExtInfo
->Mapping
[i
]), s
);
2533 AdPrint(("Resize save cutted (8)\n"));
2534 if(OS_SUCCESS(UDFStoreCachedAllocation(Vcb
, ExtInfo
->Mapping
[0].extLocation
,
2535 &TmpExtInf
, 0, UDF_PREALLOC_CLASS_DIR
))) {
2536 ExtInfo
->Mapping
[i
].extLength
= 0;
2537 ExtInfo
->Mapping
[i
].extLocation
= 0;
2542 UDFMarkSpaceAsXXX(Vcb
, 0, &(ExtInfo
->Mapping
[i
]), AS_DISCARDED
); // mark as free
2545 if((lim
-1 >= LBS
) &&
2546 (flags
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
)) {
2547 AdPrint(("i=%x, lba=%x, len=%x\n",i
,lba
,lim
));
2550 EXTENT_MAP ClrMap
[2];
2551 ClrMap
[0].extLength
= lim
& ~(LBS
-1);
2552 s
= (ExtInfo
->Mapping
[i
-1].extLength
- ClrMap
[0].extLength
) & UDF_EXTENT_LENGTH_MASK
;
2553 ClrMap
[0].extLocation
= ExtInfo
->Mapping
[i
-1].extLocation
+
2555 ClrMap
[1].extLength
=
2556 ClrMap
[1].extLocation
= 0;
2557 ASSERT((ExtInfo
->Mapping
[i
].extLocation
< ClrMap
[0].extLocation
) ||
2558 (ExtInfo
->Mapping
[i
].extLocation
>= (ClrMap
[0].extLocation
+ (ClrMap
[0].extLength
>> BSh
))));
2559 UDFCheckSpaceAllocation(Vcb
, 0, (PEXTENT_MAP
)(&ClrMap
), AS_USED
); // check if used
2560 UDFMarkSpaceAsXXX(Vcb
, 0, (PEXTENT_MAP
)(&ClrMap
), AS_DISCARDED
); // mark as free
2561 ExtInfo
->Mapping
[i
-1].extLength
= s
| (flags
<< 30);
2564 s
= UDFGetMappingLength(ExtInfo
->Mapping
);
2565 if(!MyReallocPool__((int8
*)(ExtInfo
->Mapping
), s
, (int8
**)&(ExtInfo
->Mapping
), (i
+1)*sizeof(EXTENT_MAP
))) {
2566 // This must never happen on truncate !!!
2567 AdPrint(("ResizeExtent: MyReallocPool__(8) failed\n"));
2569 ExtInfo
->Mapping
[i
].extLength
=
2570 ExtInfo
->Mapping
[i
].extLocation
= 0;
2572 AdPrint(("Resize zero (9)\n"));
2573 ASSERT(!ExtInfo
->Offset
);
2574 UDFMarkSpaceAsXXX(Vcb
, 0, ExtInfo
->Mapping
, AS_DISCARDED
); // mark as free
2575 s
= UDFGetMappingLength(ExtInfo
->Mapping
);
2576 if(!MyReallocPool__((int8
*)(ExtInfo
->Mapping
), s
, (int8
**)&(ExtInfo
->Mapping
), 2*sizeof(EXTENT_MAP
))) {
2577 // This must never happen on truncate !!!
2578 AdPrint(("ResizeExtent: MyReallocPool__(9) failed\n"));
2580 ExtInfo
->Mapping
[0].extLength
= LBS
| (EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30);
2581 ExtInfo
->Mapping
[0].extLocation
=
2582 ExtInfo
->Mapping
[1].extLength
=
2583 ExtInfo
->Mapping
[1].extLocation
= 0;
2585 if(ExtInfo
->Offset
) {
2587 // remove 1st entry pointing to FileEntry
2588 s
= UDFGetMappingLength(ExtInfo
->Mapping
);
2589 RtlMoveMemory(&(ExtInfo
->Mapping
[0]), &(ExtInfo
->Mapping
[1]), s
- sizeof(EXTENT_MAP
));
2590 if(!MyReallocPool__((int8
*)(ExtInfo
->Mapping
), s
,
2591 (int8
**)&(ExtInfo
->Mapping
), s
- sizeof(EXTENT_MAP
) )) {
2592 // This must never happen on truncate !!!
2593 AdPrint(("ResizeExtent: MyReallocPool__(10) failed\n"));
2595 Length
-= ExtInfo
->Offset
;
2596 ExtInfo
->Offset
= 0;
2598 Length
-= ExtInfo
->Offset
; // back to in-icb
2601 ExtInfo
->Length
= Length
;
2602 UDFCheckSpaceAllocation(Vcb
, 0, ExtInfo
->Mapping
, AS_USED
); // check if used
2604 for(i
=0; (ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
); i
++) {
2605 ExtPrint(("Resized Ext: type %x, loc %x, len %x\n",
2606 ExtInfo
->Mapping
[i
].extLength
>> 30, ExtInfo
->Mapping
[i
].extLocation
, ExtInfo
->Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
));
2609 return STATUS_SUCCESS
;
2610 } // end UDFResizeExtent()
2613 This routine (re)builds AllocDescs data for all allocation modes except
2614 in-ICB & resizes associated extent (FileInfo->Dloc->AllocLoc) for
2615 already allocated user data extent (FileInfo->Dloc->DataLoc).
2616 AllocMode in FileEntry pointed by FileInfo must be already initialized.
2622 IN OUT PUDF_FILE_INFO FileInfo
,
2623 OUT int8
** AllocData
2626 // PEXTENT_MAP InMap;
2633 ValidateFileInfo(FileInfo
);
2634 AdPrint(("BuildAllocDesc\n"));
2635 // get space available in the 1st LBlock after FE
2636 InitSz
= Vcb
->LBlockSize
- FileInfo
->Dloc
->FileEntryLen
;
2637 Allocs
= (int8
*)MyAllocatePool__(NonPagedPool
, InitSz
);
2639 AdPrint(("BuildAllocDesc: cant alloc %x bytes for Allocs\n", InitSz
));
2640 return STATUS_INSUFFICIENT_RESOURCES
;
2642 RtlZeroMemory(Allocs
, InitSz
);
2643 // InMap = FileInfo->Dloc->DataLoc.Mapping;
2644 UDFCheckSpaceAllocation(Vcb
, 0, InMap
, AS_USED
); // check if used
2646 // TODO: move data from mapped locations here
2648 AllocMode
= ((PFILE_ENTRY
)(FileInfo
->Dloc
->FileEntry
))->icbTag
.flags
& ICB_FLAG_ALLOC_MASK
;
2650 case ICB_FLAG_AD_IN_ICB
: {
2651 MyFreePool__(Allocs
);
2652 ASSERT(!FileInfo
->Dloc
->AllocLoc
.Mapping
);
2654 status
= STATUS_SUCCESS
;
2657 case ICB_FLAG_AD_SHORT
: {
2658 status
= UDFBuildShortAllocDescs(Vcb
, PartNum
, &Allocs
, InitSz
, FileInfo
);
2661 case ICB_FLAG_AD_LONG
: {
2662 status
= UDFBuildLongAllocDescs(Vcb
, PartNum
, &Allocs
, InitSz
, FileInfo
);
2665 /* case ICB_FLAG_AD_EXTENDED: {
2666 status = UDFBuildExtAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo);
2670 MyFreePool__(Allocs
);
2672 status
= STATUS_INVALID_PARAMETER
;
2676 *AllocData
= Allocs
;
2677 UDFCheckSpaceAllocation(Vcb
, 0, FileInfo
->Dloc
->DataLoc
.Mapping
, AS_USED
); // check if used
2680 } // end UDFBuildAllocDescs()
2683 This routine discards file's allocation
2686 UDFFreeFileAllocation(
2688 IN PUDF_FILE_INFO DirInfo
,
2689 IN PUDF_FILE_INFO FileInfo
2692 if(FileInfo
->Dloc
->DataLoc
.Offset
) {
2694 if(FileInfo
->Dloc
->DataLoc
.Mapping
) {
2695 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
==
2696 FileInfo
->Dloc
->DataLoc
.Mapping
[0].extLocation
);
2697 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, &(FileInfo
->Dloc
->DataLoc
.Mapping
[1]), AS_DISCARDED
); // free
2698 FileInfo
->Dloc
->DataLoc
.Mapping
[1].extLocation
=
2699 FileInfo
->Dloc
->DataLoc
.Mapping
[1].extLength
= 0;
2700 FileInfo
->Dloc
->DataLoc
.Mapping
[0].extLocation
= 0;
2701 FileInfo
->Dloc
->DataLoc
.Mapping
[0].extLength
= EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30;
2703 if(FileInfo
->Dloc
->AllocLoc
.Mapping
) {
2704 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
==
2705 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
);
2706 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, &(FileInfo
->Dloc
->AllocLoc
.Mapping
[1]), AS_DISCARDED
); // free
2707 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLocation
=
2708 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLength
= 0;
2709 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
= 0;
2710 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLength
= EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30;
2712 UDFFreeFESpace(Vcb
, DirInfo
, &(FileInfo
->Dloc
->FELoc
));
2714 if(FileInfo
->Dloc
->AllocLoc
.Mapping
) {
2715 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
==
2716 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
);
2717 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, &(FileInfo
->Dloc
->AllocLoc
.Mapping
[1]), AS_DISCARDED
); // free
2718 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLocation
=
2719 FileInfo
->Dloc
->AllocLoc
.Mapping
[1].extLength
= 0;
2720 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLocation
= 0;
2721 FileInfo
->Dloc
->AllocLoc
.Mapping
[0].extLength
= EXTENT_NOT_RECORDED_NOT_ALLOCATED
<< 30;
2723 UDFFreeFESpace(Vcb
, DirInfo
, &(FileInfo
->Dloc
->FELoc
));
2724 UDFMarkSpaceAsXXX(Vcb
, FileInfo
->Dloc
, FileInfo
->Dloc
->DataLoc
.Mapping
, AS_DISCARDED
); // free
2726 FileInfo
->Dloc
->DataLoc
.Modified
=
2727 FileInfo
->Dloc
->AllocLoc
.Modified
=
2728 FileInfo
->Dloc
->FELoc
.Modified
= FALSE
;
2729 } // end UDFFreeFileAllocation()
2730 #endif //UDF_READ_ONLY_BUILD
2733 This routine packs physically sequential extents into single one
2739 IN PEXTENT_INFO ExtInfo
// Extent array
2742 PEXTENT_MAP NewMap
, OldMap
;
2744 uint32 LastLba
, LastType
, OldLen
;
2745 uint32 OldSize
, NewSize
;
2750 AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
2751 AdPrint((" Length %x\n", ExtInfo
->Length
));
2753 OldMap
= ExtInfo
->Mapping
;
2754 LastLba
= OldMap
[0].extLocation
;
2755 OldLen
= (OldMap
[0].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
;
2756 LastType
= OldMap
[0].extLength
>> 30;
2758 NewSize
= UDFGetMappingLength(OldMap
);
2760 check_size
= UDFGetExtentLength(ExtInfo
->Mapping
);
2761 ASSERT(!(check_size
& (2048-1)));
2764 l
=OldMap
[0].extLength
& UDF_EXTENT_LENGTH_MASK
;
2765 // calculate required length
2766 for(i
=1; OldMap
[i
].extLength
; i
++) {
2767 if((LastType
== (OldMap
[i
].extLength
>> 30))
2769 ((OldMap
[i
].extLocation
== LastLba
+ OldLen
) ||
2770 (!OldMap
[i
].extLocation
&& !LastLba
&& (LastType
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
)))
2772 (l
+ (OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) <= UDF_MAX_EXTENT_LENGTH
)) {
2773 // we can pack two blocks in one
2774 l
+= OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2775 NewSize
-= sizeof(EXTENT_MAP
);
2777 l
= OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2779 LastLba
= OldMap
[i
].extLocation
;
2780 LastType
= OldMap
[i
].extLength
>> 30;
2781 OldLen
= (OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
;
2784 if(OldSize
<= (NewSize
+ PACK_MAPPING_THRESHOLD
)) {
2785 if(OldSize
== NewSize
)
2787 if(NewSize
>= PACK_MAPPING_THRESHOLD
)
2790 AdPrint(("Pack ExtInfo %x, Mapping %x, realloc\n", ExtInfo
, ExtInfo
->Mapping
));
2791 NewMap
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, NewSize
,
2795 // Ok, lets pack it...
2797 NewMap
[0] = OldMap
[0