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];
2798 LastLba
= OldMap
[0].extLocation
;
2799 OldLen
= (OldMap
[0].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
;
2800 LastType
= OldMap
[0].extLength
>> 30;
2801 for(i
=1; OldMap
[i
].extLength
; i
++) {
2803 ExtPrint(("oShExt: type %x, loc %x, len %x\n",
2804 OldMap
[i
].extLength
>> 30, OldMap
[i
].extLocation
, OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
));
2806 if((LastType
== (OldMap
[i
].extLength
>> 30))
2808 ((OldMap
[i
].extLocation
== LastLba
+ OldLen
) ||
2809 (!OldMap
[i
].extLocation
&& !LastLba
&& (LastType
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
)))
2811 ((NewMap
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
) + (OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) <= UDF_MAX_EXTENT_LENGTH
)) {
2812 NewMap
[j
].extLength
+= OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
;
2815 NewMap
[j
] = OldMap
[i
];
2818 ExtPrint(("nShExt: type %x, loc %x, len %x\n",
2819 NewMap
[j
].extLength
>> 30, NewMap
[j
].extLocation
, NewMap
[j
].extLength
& UDF_EXTENT_LENGTH_MASK
));
2821 LastLba
= OldMap
[i
].extLocation
;
2822 LastType
= OldMap
[i
].extLength
>> 30;
2823 OldLen
= (OldMap
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
) >> Vcb
->BlockSizeBits
;
2827 ASSERT(NewSize
== (j
+1)*sizeof(EXTENT_MAP
));
2828 NewMap
[j
].extLength
=
2829 NewMap
[j
].extLocation
= 0;
2831 ASSERT(check_size
== UDFGetExtentLength(ExtInfo
->Mapping
));
2832 ASSERT(check_size
== UDFGetExtentLength(NewMap
));
2834 AdPrint(("Pack ExtInfo %x, NewMap %x, OldMap %x\n", ExtInfo
, NewMap
, OldMap
));
2836 ExtInfo
->Mapping
= NewMap
;
2837 MyFreePool__(OldMap
);
2839 AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
2840 AdPrint((" Length %x\n", ExtInfo
->Length
));
2841 } // end UDFPackMapping()
2844 This routine expands mapping to 'frag-per-LBlock' state
2850 IN PEXTENT_INFO ExtInfo
// Extent array
2853 PEXTENT_MAP NewMapping
;
2854 PEXTENT_MAP Mapping
= ExtInfo
->Mapping
;
2855 uint32 LBS
= Vcb
->LBlockSize
;
2856 uint32 len
= (uint32
)(UDFGetExtentLength(Mapping
) >> Vcb
->LBlockSizeBits
);
2857 uint32 i
,j
, type
, base
, d
;
2860 NewMapping
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, (len
+1)*sizeof(EXTENT_MAP
),
2862 if(!NewMapping
) return STATUS_INSUFFICIENT_RESOURCES
;
2865 d
= LBS
>> Vcb
->BlockSizeBits
;
2866 for(i
=0; (l
= (Mapping
[i
].extLength
& UDF_EXTENT_LENGTH_MASK
)); i
++) {
2867 base
= Mapping
[i
].extLocation
;
2868 type
= Mapping
[i
].extLength
& UDF_EXTENT_FLAG_MASK
;
2869 for(; l
>=(LONG
)LBS
; j
++) {
2870 NewMapping
[j
].extLength
= LBS
| type
;
2871 NewMapping
[j
].extLocation
= base
;
2876 // record terminator
2878 RtlZeroMemory(&(NewMapping
[j
]), sizeof(EXTENT_MAP
));
2879 MyFreePool__(Mapping
);
2880 ExtInfo
->Mapping
= NewMapping
;
2882 return STATUS_SUCCESS
;
2883 } // end UDFUnPackMapping()
2886 Relocate a part of extent that starts from relative (inside extent)
2887 block number 'ExtBlock' and has length of 'BC' blocks to continuous
2888 run which starts at block 'Lba'
2893 IN PEXTENT_INFO ExtInfo
,
2899 return STATUS_ACCESS_DENIED
;
2903 This routine checks if all the data required is in cache.
2908 IN PEXTENT_INFO ExtInfo
, // Extent array
2909 IN int64 Offset
, // offset in extent
2914 BOOLEAN retstat
= FALSE
;
2915 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
2916 uint32 to_read
, Lba
, sect_offs
, flags
, i
;
2918 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
/*FALSE*//*ForWrite*/);
2919 if(!ExtInfo
|| !ExtInfo
->Mapping
) goto EO_IsCached
;
2925 // prevent reading out of data space
2926 if(Offset
> ExtInfo
->Length
) goto EO_IsCached
;
2927 if(Offset
+Length
> ExtInfo
->Length
) goto EO_IsCached
;
2928 Offset
+= ExtInfo
->Offset
; // used for in-ICB data
2929 // read maximal possible part of each frag of extent
2930 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_read
, &flags
, &i
);
2931 while(((LONG
)Length
) > 0) {
2933 if(Lba
== LBA_OUT_OF_EXTENT
) goto EO_IsCached
;
2935 // check for reading tail
2936 to_read
= min(to_read
, Length
);
2937 if(flags
== EXTENT_RECORDED_ALLOCATED
) {
2938 retstat
= UDFIsDataCached(Vcb
, Lba
, (to_read
+sect_offs
+Vcb
->BlockSize
-1)>>Vcb
->BlockSizeBits
);
2939 if(!retstat
) goto EO_IsCached
;
2940 } else if(ForWrite
) {
2945 Lba
= UDFNextExtentToLba(Vcb
, Extent
, &to_read
, &flags
, &i
);
2950 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
2953 } // end UDFIsExtentCached()
2956 This routine reads cached data only.
2959 UDFReadExtentCached(
2961 IN PEXTENT_INFO ExtInfo, // Extent array
2962 IN int64 Offset, // offset in extent
2965 OUT uint32* ReadBytes
2969 if(!ExtInfo || !ExtInfo->Mapping) return STATUS_INVALID_PARAMETER;
2971 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
2972 uint32 to_read, Lba, sect_offs, flags, _ReadBytes;
2974 // prevent reading out of data space
2975 if(Offset > ExtInfo->Length) return STATUS_END_OF_FILE;
2976 if(Offset+Length > ExtInfo->Length) Length = (uint32)(ExtInfo->Length - Offset);
2977 Offset += ExtInfo->Offset; // used for in-ICB data
2978 // read maximal possible part of each frag of extent
2979 while(((LONG)Length) > 0) {
2980 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_read, &flags, NULL);
2982 if(Lba == LBA_OUT_OF_EXTENT) return STATUS_END_OF_FILE;
2983 // check for reading tail
2984 to_read = (to_read < Length) ?
2986 if(flags == EXTENT_RECORDED_ALLOCATED) {
2987 status = UDFReadDataCached(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_read, Buffer, &_ReadBytes);
2988 (*ReadBytes) += _ReadBytes;
2990 RtlZeroMemory(Buffer, to_read);
2991 (*ReadBytes) += to_read;
2992 status = STATUS_SUCCESS;
2994 if(!OS_SUCCESS(status)) return status;
2995 // prepare for reading next frag...
3000 return STATUS_SUCCESS;
3001 } // end UDFReadExtentCached()*/
3004 This routine reads data at any offset from specified extent.
3009 IN PEXTENT_INFO ExtInfo
, // Extent array
3010 IN int64 Offset
, // offset in extent
3014 OUT uint32
* ReadBytes
3018 if(!ExtInfo
|| !ExtInfo
->Mapping
) return STATUS_INVALID_PARAMETER
;
3019 ASSERT((uint32
)Buffer
> 0x1000);
3021 AdPrint(("Read ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
3023 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
3024 uint32 to_read
, Lba
, sect_offs
, flags
, _ReadBytes
;
3026 // prevent reading out of data space
3027 if(Offset
> ExtInfo
->Length
) return STATUS_END_OF_FILE
;
3028 if(Offset
+Length
> ExtInfo
->Length
) Length
= (uint32
)(ExtInfo
->Length
- Offset
);
3029 Offset
+= ExtInfo
->Offset
; // used for in-ICB data
3030 // read maximal possible part of each frag of extent
3031 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_read
, &flags
, &_ReadBytes
);
3034 if(Lba
== LBA_OUT_OF_EXTENT
) return STATUS_END_OF_FILE
;
3035 Extent
+= (_ReadBytes
+ 1);
3036 // check for reading tail
3037 to_read
= min(to_read
, Length
);
3038 if(flags
== EXTENT_RECORDED_ALLOCATED
) {
3039 status
= UDFReadData(Vcb
, TRUE
, ( ((uint64
)Lba
) << Vcb
->BlockSizeBits
) + sect_offs
, to_read
, Direct
, Buffer
, &_ReadBytes
);
3040 (*ReadBytes
) += _ReadBytes
;
3041 if(!OS_SUCCESS(status
)) return status
;
3043 RtlZeroMemory(Buffer
, to_read
);
3044 (*ReadBytes
) += to_read
;
3046 // prepare for reading next frag...
3052 // Offset += to_read;
3053 Lba
= UDFNextExtentToLba(Vcb
, Extent
, &to_read
, &flags
, &_ReadBytes
);
3056 return STATUS_SUCCESS
;
3057 } // end UDFReadExtent()
3060 This routine reads and builds mapping for
3061 specified amount of data at any offset from specified extent.
3062 Size of output buffer is limited by *_SubExtInfoSz
3065 UDFReadExtentLocation(
3067 IN PEXTENT_INFO ExtInfo
, // Extent array
3068 IN int64 Offset
, // offset in extent to start SubExtent from
3069 OUT PEXTENT_MAP
* _SubExtInfo
, // SubExtent mapping array
3070 IN OUT uint32
* _SubExtInfoSz
, // IN: maximum number of fragments to get
3071 // OUT: actually obtained fragments
3072 OUT int64
* _NextOffset
// offset, caller can start from to continue
3075 if(!ExtInfo
|| !ExtInfo
->Mapping
)
3076 return STATUS_INVALID_PARAMETER
;
3078 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
3079 PEXTENT_MAP SubExtInfo
;
3080 uint32 to_read
, Lba
, sect_offs
, flags
, Skip_MapEntries
;
3081 int32 SubExtInfoSz
= *_SubExtInfoSz
;
3084 // OSSTATUS status = STATUS_BUFFER_OVERFLOW;
3086 (*_SubExtInfo
) = NULL
;
3087 (*_SubExtInfoSz
) = 0;
3088 NextOffset
= Offset
;
3089 // prevent reading out of data space
3090 if(Offset
>= ExtInfo
->Length
)
3091 return STATUS_END_OF_FILE
;
3092 Length
= ExtInfo
->Length
- Offset
;
3093 Offset
+= ExtInfo
->Offset
; // used for in-ICB data
3094 // read maximal possible part of each frag of extent
3095 SubExtInfo
= (PEXTENT_MAP
)MyAllocatePoolTag__(NonPagedPool
, SubExtInfoSz
*sizeof(EXTENT_MAP
),
3097 (*_SubExtInfo
) = SubExtInfo
;
3099 return STATUS_INSUFFICIENT_RESOURCES
;
3101 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_read
, &flags
, &Skip_MapEntries
);
3102 while(Length
&& SubExtInfoSz
) {
3104 if(Lba
== LBA_OUT_OF_EXTENT
) {
3106 return STATUS_END_OF_FILE
;
3108 Extent
+= (Skip_MapEntries
+ 1);
3109 // check for reading tail
3110 to_read
= (int32
)min((int64
)to_read
, Length
);
3111 SubExtInfo
->extLength
= to_read
;
3112 if(flags
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
3113 SubExtInfo
->extLocation
= LBA_NOT_ALLOCATED
;
3115 if(flags
== EXTENT_NOT_RECORDED_ALLOCATED
) {
3116 ASSERT(!(Lba
& 0x80000000));
3117 SubExtInfo
->extLocation
= Lba
| 0x80000000;
3119 SubExtInfo
->extLocation
= Lba
;
3123 NextOffset
+= to_read
;
3124 // prepare for reading next frag...
3127 // status = STATUS_SUCCESS;
3131 Lba
= UDFNextExtentToLba(Vcb
, Extent
, &to_read
, &flags
, &Skip_MapEntries
);
3134 (*_NextOffset
) = NextOffset
;
3135 return STATUS_SUCCESS
;
3136 } // end UDFReadExtentLocation()
3139 #pragma warning(push)
3140 #pragma warning(disable:4035) // re-enable below
3150 Length
/= sizeof(uint32
);
3151 for(i
=0; i
<Length
; i
++) {
3152 if( ((uint32
*)Buffer
)[i
] )
3155 return Length
*sizeof(uint32
);
3159 #pragma warning(pop) // re-enable warning #4035
3162 #ifndef UDF_READ_ONLY_BUILD
3164 This routine writes data at any offset to specified extent.
3169 IN PEXTENT_INFO ExtInfo
, // Extent array
3170 IN int64 Offset
, // offset in extent
3172 IN BOOLEAN Direct
, // setting this flag delays flushing of given
3173 // data to indefinite term
3175 OUT uint32
* WrittenBytes
3178 if(!ExtInfo
|| !ExtInfo
->Mapping
)
3179 return STATUS_INVALID_PARAMETER
;
3181 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
3182 uint32 to_write
, Lba
, sect_offs
, flags
;
3184 uint32 _WrittenBytes
;
3186 // BOOLEAN already_prepared = FALSE;
3187 // BOOLEAN prepare = !Buffer;
3189 AdPrint(("Write ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
3191 Offset
+= ExtInfo
->Offset
; // used for in-ICB data
3192 // write maximal possible part of each frag of extent
3193 while(((LONG
)Length
) > 0) {
3194 UDFCheckSpaceAllocation(Vcb
, 0, Extent
, AS_USED
); // check if used
3195 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_write
, &flags
, NULL
);
3197 if(Lba
== LBA_OUT_OF_EXTENT
) {
3198 return STATUS_END_OF_FILE
;
3200 /* if((to_write < Length) &&
3201 !Direct && !prepare && !already_prepared) {
3202 // rebuild mapping, allocate space, etc.
3203 // to indicate this, set Buffer to NULL
3204 AdPrint(("UDFWriteExtent: Prepare\n"));
3207 status = UDFWriteExtent(Vcb, ExtInfo, Offset, Length, *//*Direct*//*FALSE, NULL, &_WrittenBytes);
3208 if(!OS_SUCCESS(status)) {
3211 Extent = ExtInfo->Mapping;
3212 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL);
3213 already_prepared = TRUE;
3215 if(flags
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
3216 // here we should allocate space for this extent
3217 if(!OS_SUCCESS(status
= UDFMarkNotAllocatedAsAllocated(Vcb
, Offset
, to_write
, ExtInfo
)))
3219 Extent
= ExtInfo
->Mapping
;
3220 UDFCheckSpaceAllocation(Vcb
, 0, Extent
, AS_USED
); // check if used
3221 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_write
, &flags
, NULL
);
3222 if(Lba
== LBA_OUT_OF_EXTENT
) {
3223 return STATUS_END_OF_FILE
;
3225 // we have already re-read Lba
3228 // we may need to re-read Lba if some changes are
3229 // made while converting from Alloc-Not-Rec
3232 // check if writing to not recorded allocated
3233 // in this case we must pad blocks with zeros around
3236 // ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|...
3241 // ...|000ddddd|dddddddd|dd000000|...
3244 // sect_offs sect_offs+to_write
3246 // .<-- to_write -->.
3248 to_write
= min(to_write
, Length
);
3249 if(flags
== EXTENT_NOT_RECORDED_ALLOCATED
) {
3250 if(!OS_SUCCESS(status
= UDFMarkAllocatedAsRecorded(Vcb
, Offset
, to_write
, ExtInfo
)))
3252 Extent
= ExtInfo
->Mapping
;
3253 UDFCheckSpaceAllocation(Vcb
, 0, Extent
, AS_USED
); // check if used
3255 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_write
, &flags
, NULL
);
3256 to_write
= min(to_write
, Length
);
3259 we must fill 1st block with zeros in 1 of 2 cases:
3260 1) start offset is not aligned on LBlock boundary
3262 2) end offset is not aligned on LBlock boundary and lays in
3265 we must fill last block with zeros if both
3266 1) end offset is not aligned on LBlock boundary
3268 2) end offset DOESN'T lay in the 1st LBlock
3272 // pad 1st logical block
3273 if((sect_offs
|| (sect_offs
+ to_write
< Vcb
->LBlockSize
) )
3276 status
= UDFWriteData(Vcb
, TRUE
,
3277 ( ((uint64
)Lba
) << Vcb
->BlockSizeBits
),
3278 Vcb
->LBlockSize
, Direct
, Vcb
->ZBuffer
, &_WrittenBytes
);
3279 if(!OS_SUCCESS(status
))
3282 // pad last logical block
3283 if((sect_offs
+ to_write
> Vcb
->LBlockSize
) &&
3284 (sect_offs
+ to_write
) & (Vcb
->LBlockSize
- 1)) {
3285 status
= UDFWriteData(Vcb
, TRUE
,
3286 (( ((uint64
)Lba
) << Vcb
->BlockSizeBits
) + sect_offs
+ to_write
) & ~((int64
)(Vcb
->LBlockSize
)-1),
3287 Vcb
->LBlockSize
, Direct
, Vcb
->ZBuffer
, &_WrittenBytes
);
3289 if(!OS_SUCCESS(status
))
3292 status = STATUS_SUCCESS;
3297 status
= UDFWriteData(Vcb
, TRUE
, ( ((uint64
)Lba
) << Vcb
->BlockSizeBits
) + sect_offs
, to_write
, Direct
, Buffer
, &_WrittenBytes
);
3298 *WrittenBytes
+= _WrittenBytes
;
3299 if(!OS_SUCCESS(status
)) return status
;
3301 status = STATUS_SUCCESS;
3302 *WrittenBytes += to_write;
3304 // prepare for writing next frag...
3309 AdPrint(("Write: ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
3310 return STATUS_SUCCESS
;
3311 } // end UDFWriteExtent()
3315 This routine zeroes/deallocates data at any offset to specified extent.
3320 IN PEXTENT_INFO ExtInfo
, // Extent array
3321 IN int64 Offset
, // offset in extent
3323 IN BOOLEAN Deallocate
, // deallocate frag or just mark as unrecorded
3324 IN BOOLEAN Direct
, // setting this flag delays flushing of given
3325 // data to indefinite term
3326 OUT uint32
* WrittenBytes
3329 if(!ExtInfo
|| !ExtInfo
->Mapping
)
3330 return STATUS_INVALID_PARAMETER
;
3332 PEXTENT_MAP Extent
= ExtInfo
->Mapping
; // Extent array
3333 uint32 to_write
, Lba
, sect_offs
, flags
;
3335 uint32 _WrittenBytes
;
3336 uint32 LBS
= Vcb
->LBlockSize
;
3338 AdPrint(("Zero ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
3340 Offset
+= ExtInfo
->Offset
; // used for in-ICB data
3341 // fill/deallocate maximal possible part of each frag of extent
3342 while(((LONG
)Length
) > 0) {
3343 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_write
, &flags
, NULL
);
3345 if(Lba
== LBA_OUT_OF_EXTENT
) {
3346 return STATUS_END_OF_FILE
;
3348 // check for writing tail
3349 to_write
= min(to_write
, Length
);
3351 if(flags
== EXTENT_NOT_RECORDED_NOT_ALLOCATED
) {
3352 // here we should do nothing
3353 *WrittenBytes
+= to_write
;
3355 if(flags
== EXTENT_NOT_RECORDED_ALLOCATED
) {
3356 // we should just deallocate this frag
3358 if(!OS_SUCCESS(status
= UDFMarkAllocatedAsNotAllocated(Vcb
, Offset
, to_write
, ExtInfo
)))
3361 Extent
= ExtInfo
->Mapping
;
3362 *WrittenBytes
+= to_write
;
3364 // fill tail of the 1st Block with ZEROs
3366 status
= UDFWriteData(Vcb
, TRUE
, ( ((uint64
)Lba
) << Vcb
->BlockSizeBits
) + sect_offs
,
3367 min(to_write
, LBS
-sect_offs
),
3368 Direct
, Vcb
->ZBuffer
, &_WrittenBytes
);
3369 *WrittenBytes
+= _WrittenBytes
;
3370 if(!OS_SUCCESS(status
))
3372 Offset
+= _WrittenBytes
;
3373 Length
-= _WrittenBytes
;
3374 to_write
-= _WrittenBytes
;
3375 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_write
, &flags
, NULL
);
3376 ASSERT(flags
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
);
3377 ASSERT(flags
!= EXTENT_NOT_RECORDED_ALLOCATED
);
3380 // deallocate Blocks
3381 if(to_write
>= LBS
) {
3382 // use 'sect_offs' as length of extent to be deallocated
3383 sect_offs
= to_write
& ~(LBS
- 1);
3385 status
= UDFMarkAllocatedAsNotAllocated(Vcb
, Offset
, sect_offs
, ExtInfo
);
3387 status
= UDFMarkRecordedAsAllocated(Vcb
, Offset
, sect_offs
, ExtInfo
);
3389 if(!OS_SUCCESS(status
))
3391 // reload extent mapping
3392 Extent
= ExtInfo
->Mapping
;
3393 Offset
+= sect_offs
;
3394 Length
-= sect_offs
;
3395 *WrittenBytes
+= sect_offs
;
3396 to_write
-= sect_offs
;
3397 Lba
= UDFExtentOffsetToLba(Vcb
, Extent
, Offset
, §_offs
, &to_write
, &flags
, NULL
);
3398 ASSERT(flags
!= EXTENT_NOT_RECORDED_NOT_ALLOCATED
);
3399 ASSERT(flags
!= EXTENT_NOT_RECORDED_ALLOCATED
);
3402 // fill beginning of the last Block with ZEROs
3404 status
= UDFWriteData(Vcb
, TRUE
, ( ((uint64
)Lba
) << Vcb
->BlockSizeBits
), to_write
, Direct
, Vcb
->ZBuffer
, &_WrittenBytes
);
3405 *WrittenBytes
+= _WrittenBytes
;
3406 if(!OS_SUCCESS(status
))
3408 ASSERT(to_write
== _WrittenBytes
);
3411 AdPrint(("Zero... ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
3412 // prepare for filling next frag...
3416 AdPrint(("Zero: ExtInfo %x, Mapping %x\n", ExtInfo
, ExtInfo
->Mapping
));
3417 return STATUS_SUCCESS
;
3418 } // end UDFZeroExtent()
3420 #endif //UDF_READ_ONLY_BUILD