1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 ////////////////////////////////////////////////////////////////////
12 This file contains filesystem-specific routines
13 responsible for disk space management
19 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_REMAP
21 typedef struct _UDF_VERIFY_ITEM
{
27 } UDF_VERIFY_ITEM
, *PUDF_VERIFY_ITEM
;
29 typedef struct _UDF_VERIFY_REQ_RANGE
{
32 } UDF_VERIFY_REQ_RANGE
, *PUDF_VERIFY_REQ_RANGE
;
34 #define MAX_VREQ_RANGES 128
36 typedef struct _UDF_VERIFY_REQ
{
40 UDF_VERIFY_REQ_RANGE vr
[MAX_VREQ_RANGES
];
42 WORK_QUEUE_ITEM VerifyItem
;
44 } UDF_VERIFY_REQ
, *PUDF_VERIFY_REQ
;
48 PUDF_VERIFY_CTX VerifyCtx
,
49 PUDF_VERIFY_ITEM vItem
57 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
59 OSSTATUS status
= STATUS_SUCCESS
;
60 BOOLEAN res_inited
= FALSE
;
62 if(VerifyCtx
->VInited
) {
63 KdPrint(("Already inited\n"));
64 return STATUS_SUCCESS
;
68 RtlZeroMemory(VerifyCtx
, sizeof(UDF_VERIFY_CTX
));
69 if(!Vcb
->VerifyOnWrite
) {
70 KdPrint(("Verify is disabled\n"));
71 return STATUS_SUCCESS
;
74 KdPrint(("Verify is not intended for CD/DVD-R\n"));
75 return STATUS_SUCCESS
;
77 if(!OS_SUCCESS(status
= ExInitializeResourceLite(&(VerifyCtx
->VerifyLock
)))) {
81 VerifyCtx
->ItemCount
= 0;
82 VerifyCtx
->StoredBitMap
= (uint8
*)DbgAllocatePoolWithTag(PagedPool
, (i
= (Vcb
->LastPossibleLBA
+1+7)>>3), 'mNWD' );
83 if(VerifyCtx
->StoredBitMap
) {
84 RtlZeroMemory(VerifyCtx
->StoredBitMap
, i
);
86 KdPrint(("Can't alloc verify bitmap for %x blocks\n", Vcb
->LastPossibleLBA
));
87 try_return(status
= STATUS_INSUFFICIENT_RESOURCES
);
89 InitializeListHead(&(VerifyCtx
->vrfList
));
90 KeInitializeEvent(&(VerifyCtx
->vrfEvent
), SynchronizationEvent
, FALSE
);
91 VerifyCtx
->WaiterCount
= 0;
92 VerifyCtx
->VInited
= TRUE
;
98 if(!OS_SUCCESS(status
)) {
100 ExDeleteResourceLite(&(VerifyCtx
->VerifyLock
));
109 PUDF_VERIFY_CTX VerifyCtx
114 while(VerifyCtx
->QueuedCount
) {
115 KdPrint(("UDFVWaitQueued: wait for completion (%d)\n", VerifyCtx
->QueuedCount
));
116 w
= InterlockedIncrement((PLONG
)&(VerifyCtx
->WaiterCount
));
117 KdPrint((" %d waiters\n", w
));
118 DbgWaitForSingleObject(&(VerifyCtx
->vrfEvent
), NULL
);
119 if(w
= InterlockedDecrement((PLONG
)&(VerifyCtx
->WaiterCount
))) {
120 KdPrint((" still %d waiters, q %d\n", w
, VerifyCtx
->QueuedCount
));
121 if(!VerifyCtx
->QueuedCount
) {
122 KdPrint((" pulse event\n", w
));
123 KeSetEvent(&(VerifyCtx
->vrfEvent
), 0, FALSE
);
128 } // end UDFVWaitQueued()
135 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
137 PUDF_VERIFY_ITEM vItem
;
139 if(!VerifyCtx
->VInited
) {
143 KdPrint(("UDFVRelease: wait for completion\n"));
144 UDFVWaitQueued(VerifyCtx
);
146 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
148 Link
= VerifyCtx
->vrfList
.Flink
;
150 while(Link
!= &(VerifyCtx
->vrfList
)) {
151 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
153 //DbgFreePool(vItem);
154 UDFVRemoveBlock(VerifyCtx
, vItem
);
156 VerifyCtx
->VInited
= FALSE
;
158 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
160 ExDeleteResourceLite(&(VerifyCtx
->VerifyLock
));
161 DbgFreePool(VerifyCtx
->StoredBitMap
);
163 RtlZeroMemory(VerifyCtx
, sizeof(UDF_VERIFY_CTX
));
166 } // end UDFVRelease()
176 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
177 PUDF_VERIFY_ITEM vItem
;
179 KdPrint(("v-add %x\n", LBA
));
181 vItem
= (PUDF_VERIFY_ITEM
)DbgAllocatePoolWithTag(PagedPool
, sizeof(UDF_VERIFY_ITEM
)+Vcb
->BlockSize
, 'bvWD');
184 RtlCopyMemory(vItem
+1, Buffer
, Vcb
->BlockSize
);
186 vItem
->crc
= crc32((PUCHAR
)Buffer
, Vcb
->BlockSize
);
187 vItem
->Buffer
= (PUCHAR
)(vItem
+1);
188 vItem
->queued
= FALSE
;
189 InitializeListHead(&(vItem
->vrfList
));
190 InsertTailList(Link
, &(vItem
->vrfList
));
191 UDFSetBit(VerifyCtx
->StoredBitMap
, LBA
);
192 VerifyCtx
->ItemCount
++;
194 } // end UDFVStoreBlock()
200 PUDF_VERIFY_ITEM vItem
203 KdPrint(("v-upd %x\n", vItem
->lba
));
204 RtlCopyMemory(vItem
+1, Buffer
, Vcb
->BlockSize
);
205 vItem
->crc
= crc32((PUCHAR
)Buffer
, Vcb
->BlockSize
);
207 } // end UDFVUpdateBlock()
211 PUDF_VERIFY_CTX VerifyCtx
,
212 PUDF_VERIFY_ITEM vItem
215 KdPrint(("v-del %x\n", vItem
->lba
));
216 UDFClrBit(VerifyCtx
->StoredBitMap
, vItem
->lba
);
217 RemoveEntryList(&(vItem
->vrfList
));
218 VerifyCtx
->ItemCount
--;
221 } // end UDFVUpdateBlock()
226 IN
void* Buffer
, // Target buffer
229 // OUT uint32* WrittenBytes,
234 PUDF_VERIFY_ITEM vItem
;
235 //PUDF_VERIFY_ITEM vItem1;
236 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
241 if(!VerifyCtx
->VInited
) {
242 return STATUS_SUCCESS
;
245 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
247 for(i
=0, n
=0; i
<BCount
; i
++) {
248 if(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
)) {
249 // some blocks are remembered
257 Link
= VerifyCtx
->vrfList
.Blink
;
258 while(Link
!= &(VerifyCtx
->vrfList
)) {
259 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
261 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
262 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, vItem
->lba
));
263 UDFVUpdateBlock(Vcb
, ((PUCHAR
)Buffer
)+(vItem
->lba
-LBA
)*Vcb
->BlockSize
, vItem
);
274 // find remembered blocks (the 1st one)
275 Link
= VerifyCtx
->vrfList
.Blink
;
276 while(Link
!= &(VerifyCtx
->vrfList
)) {
277 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
279 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
280 //UDFVRemoveBlock(VerifyCtx, vItem);
285 // check if contiguous
287 prev_lba
= vItem
->lba
;
290 while((i
< n
) && (Link
!= &(VerifyCtx
->vrfList
))) {
291 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
293 if(vItem
->lba
> LBA
|| vItem
->lba
>= LBA
+BCount
) {
297 if(vItem
->lba
< prev_lba
) {
301 prev_lba
= vItem
->lba
;
308 // drop all and add again
312 for(i
=0; i
<BCount
; i
++) {
313 if(vItem
->lba
== LBA
+i
) {
314 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
315 UDFVUpdateBlock(Vcb
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, vItem
);
318 if(vItem1
->lba
== LBA
+i
) {
319 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
320 UDFVUpdateBlock(Vcb
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, vItem1
);
323 if(vItem1
->lba
> LBA
+i
) {
324 // just insert this block
325 ASSERT(!UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
326 UDFVStoreBlock(Vcb
, LBA
+i
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, &(vItem1
->vrfList
));
328 vItem
= CONTAINING_RECORD( vItem
->vrfList
.Blink
, UDF_VERIFY_ITEM
, vrfList
);
332 Link
= VerifyCtx
->vrfList
.Blink
;
334 while(Link
!= &(VerifyCtx
->vrfList
)) {
335 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
337 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
338 UDFVRemoveBlock(VerifyCtx
, vItem
);
351 // remember all blocks
352 for(i
=0; i
<BCount
; i
++) {
353 ASSERT(!UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
354 UDFVStoreBlock(Vcb
, LBA
+i
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, &(VerifyCtx
->vrfList
));
358 if(VerifyCtx
->ItemCount
> UDF_MAX_VERIFY_CACHE
) {
359 UDFVVerify(Vcb
, UFD_VERIFY_FLAG_LOCKED
);
362 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
364 if(VerifyCtx
->ItemCount
> UDF_MAX_VERIFY_CACHE
*2) {
365 //UDFVVerify(Vcb, UFD_VERIFY_FLAG_LOCKED);
366 // TODO: make some delay
369 return STATUS_SUCCESS
;
376 IN
void* Buffer
, // Target buffer
379 // OUT uint32* ReadBytes,
384 PUDF_VERIFY_ITEM vItem
;
385 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
389 OSSTATUS status
= STATUS_SUCCESS
;
392 if(!VerifyCtx
->VInited
) {
393 return STATUS_SUCCESS
;
394 //return STATUS_UNSUCCESSFUL;
397 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
399 for(i
=0, n
=0; i
<BCount
; i
++) {
400 if(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
)) {
401 // some blocks are remembered
407 // no blocks are remembered
408 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
409 return STATUS_SUCCESS
;
412 Link
= VerifyCtx
->vrfList
.Flink
;
414 while(Link
!= &(VerifyCtx
->vrfList
)) {
415 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
417 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
418 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, vItem
->lba
));
420 if(!(Flags
& PH_READ_VERIFY_CACHE
)) {
421 crc
= crc32((PUCHAR
)Buffer
+(vItem
->lba
- LBA
)*Vcb
->BlockSize
, Vcb
->BlockSize
);
422 if(vItem
->crc
!= crc
) {
423 KdPrint(("UDFVRead: stored %x != %x\n", vItem
->crc
, crc
));
424 RtlCopyMemory((PUCHAR
)Buffer
+(vItem
->lba
- LBA
)*Vcb
->BlockSize
, vItem
->Buffer
, Vcb
->BlockSize
);
425 status
= STATUS_FT_WRITE_RECOVERY
;
427 if(!(bm
= (uint32
*)(Vcb
->BSBM_Bitmap
))) {
428 crc
= (Vcb
->LastPossibleLBA
+1+7) >> 3; // reuse 'crc' variable
429 bm
= (uint32
*)(Vcb
->BSBM_Bitmap
= (int8
*)DbgAllocatePoolWithTag(NonPagedPool
, crc
, 'mNWD' ));
431 RtlZeroMemory(bm
, crc
);
433 KdPrint(("Can't alloc BSBM for %x blocks\n", Vcb
->LastPossibleLBA
));
437 UDFSetBit__(bm
, vItem
->lba
);
438 KdPrint(("Set BB @ %#x\n", vItem
->lba
));
441 bm
= (uint32
*)(Vcb
->FSBM_Bitmap
);
443 UDFSetUsedBit(bm
, vItem
->lba
);
444 KdPrint(("Set BB @ %#x as used\n", vItem
->lba
));
446 #endif //_BROWSE_UDF_
451 KdPrint(("UDFVRead: get cached @ %x\n", vItem
->lba
));
452 RtlCopyMemory((PUCHAR
)Buffer
+(vItem
->lba
- LBA
)*Vcb
->BlockSize
, vItem
->Buffer
, Vcb
->BlockSize
);
455 // no more blocks expected
461 if((status
== STATUS_SUCCESS
&& !(Flags
& PH_KEEP_VERIFY_CACHE
)) || (Flags
& PH_FORGET_VERIFIED
)) {
462 // ok, forget this, no errors found
463 Link
= VerifyCtx
->vrfList
.Flink
;
465 while(Link
!= &(VerifyCtx
->vrfList
)) {
466 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
468 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
470 UDFVRemoveBlock(VerifyCtx
, vItem
);
472 // no more blocks expected
479 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
493 PUDF_VERIFY_ITEM vItem
;
494 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
497 OSSTATUS status
= STATUS_SUCCESS
;
499 if(!VerifyCtx
->VInited
) {
500 return STATUS_UNSUCCESSFUL
;
503 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
505 for(i
=0, n
=0; i
<BCount
; i
++) {
506 if(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
)) {
507 // some blocks are remembered
513 // no blocks are remembered
514 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
515 return STATUS_SUCCESS
;
518 Link
= VerifyCtx
->vrfList
.Flink
;
520 while(Link
!= &(VerifyCtx
->vrfList
)) {
521 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
523 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
525 UDFVRemoveBlock(VerifyCtx
, vItem
);
527 // no more blocks expected
533 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
536 } // end UDFVForget()
540 PUDF_VERIFY_REQ VerifyReq
543 PVCB Vcb
= VerifyReq
->Vcb
;
548 ReadBytes
= (ULONG
)Vcb
;
550 if(Vcb
->SparingCountFree
) {
551 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
);
552 for(i
=0; i
<VerifyReq
->nReq
; i
++) {
553 RC
= UDFTIOVerify(Vcb
,
554 VerifyReq
->Buffer
, // Target buffer
555 VerifyReq
->vr
[i
].BCount
<< Vcb
->BlockSizeBits
,
556 VerifyReq
->vr
[i
].lba
,
558 PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
/*| PH_LOCK_CACHE*/);
560 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
562 for(i
=0; i
<VerifyReq
->nReq
; i
++) {
563 KdPrint(("!!! No more space for remap !!!\n"));
564 KdPrint((" try del from verify cache @ %x\n", VerifyReq
->vr
[i
].lba
));
565 RC
= UDFVRead(Vcb
, VerifyReq
->Buffer
, VerifyReq
->vr
[i
].BCount
, VerifyReq
->vr
[i
].lba
,
566 PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
);
570 for(i
=0; i
<VerifyReq
->nReq
; i
++) {
571 if(Vcb
->SparingCountFree
) {
572 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
);
573 RC
= UDFTIOVerify(Vcb
,
574 VerifyReq
->Buffer
, // Target buffer
575 VerifyReq
->vr
[i
].BCount
<< Vcb
->BlockSizeBits
,
576 VerifyReq
->vr
[i
].lba
,
578 PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
/*| PH_LOCK_CACHE*/);
579 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
581 KdPrint(("!!! No more space for remap !!!\n"));
582 KdPrint((" try del from verify cache @ %x\n", VerifyReq
->vr
[i
].lba
));
583 RC
= UDFVRead(Vcb
, VerifyReq
->Buffer
, VerifyReq
->vr
[i
].BCount
, VerifyReq
->vr
[i
].lba
,
584 PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
);
588 DbgFreePool(VerifyReq
->Buffer
);
589 DbgFreePool(VerifyReq
);
590 InterlockedDecrement((PLONG
)&(Vcb
->VerifyCtx
.QueuedCount
));
591 KdPrint((" QueuedCount = %d\n", Vcb
->VerifyCtx
.QueuedCount
));
592 KdPrint((" Setting event...\n"));
593 KeSetEvent(&(Vcb
->VerifyCtx
.vrfEvent
), 0, FALSE
);
595 } // end UDFVWorkItem()
603 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
605 PUDF_VERIFY_ITEM vItem
;
606 PUDF_VERIFY_REQ VerifyReq
= NULL
;
607 ULONG len
, max_len
=0;
611 BOOLEAN do_vrf
= FALSE
;
613 if(!VerifyCtx
->VInited
) {
616 if(VerifyCtx
->QueuedCount
) {
617 if(Flags
& UFD_VERIFY_FLAG_WAIT
) {
618 KdPrint((" wait for verify flush\n"));
621 KdPrint((" verify flush already queued\n"));
625 if(!(Flags
& (UFD_VERIFY_FLAG_FORCE
| UFD_VERIFY_FLAG_BG
))) {
626 if(VerifyCtx
->ItemCount
< UDF_MAX_VERIFY_CACHE
) {
631 if(!(Flags
& UFD_VERIFY_FLAG_LOCKED
)) {
632 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
635 if(Flags
& UFD_VERIFY_FLAG_FORCE
) {
636 i
= VerifyCtx
->ItemCount
;
638 if(VerifyCtx
->ItemCount
>= UDF_MAX_VERIFY_CACHE
) {
639 i
= VerifyCtx
->ItemCount
- UDF_VERIFY_CACHE_LOW
;
641 i
= min(UDF_VERIFY_CACHE_GRAN
, VerifyCtx
->ItemCount
);
645 Link
= VerifyCtx
->vrfList
.Flink
;
650 ASSERT(Link
!= &(VerifyCtx
->vrfList
));
652 if(Link == &(VerifyCtx->vrfList)) {
659 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
663 if(!vItem
->queued
&& (prev_lba
+len
== vItem
->lba
)) {
664 vItem
->queued
= TRUE
;
671 prev_lba
= vItem
->lba
;
674 if((i
== 1) && len
) {
683 VerifyReq
= (PUDF_VERIFY_REQ
)DbgAllocatePoolWithTag(NonPagedPool
, sizeof(UDF_VERIFY_REQ
), 'bNWD');
685 RtlZeroMemory(VerifyReq
, sizeof(UDF_VERIFY_REQ
));
686 VerifyReq
->Vcb
= Vcb
;
691 VerifyReq
->vr
[VerifyReq
->nReq
].lba
= prev_lba
;
692 VerifyReq
->vr
[VerifyReq
->nReq
].BCount
= len
;
698 if((VerifyReq
->nReq
>= MAX_VREQ_RANGES
) || (i
== 1)) {
700 VerifyReq
->Buffer
= (PUCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, max_len
* Vcb
->BlockSize
, 'bNWD');
701 if(VerifyReq
->Buffer
) {
702 InterlockedIncrement((PLONG
)&(VerifyCtx
->QueuedCount
));
704 ExInitializeWorkItem( &(VerifyReq
->VerifyItem
),
705 (PWORKER_THREAD_ROUTINE
) UDFVWorkItem
,
707 ExQueueWorkItem( &(VerifyReq
->VerifyItem
), CriticalWorkQueue
);
709 UDFVWorkItem(VerifyReq
);
712 DbgFreePool(VerifyReq
);
720 prev_lba
= vItem
->lba
;
726 if(!(Flags
& UFD_VERIFY_FLAG_LOCKED
)) {
727 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
729 if(Flags
& UFD_VERIFY_FLAG_WAIT
) {
731 KdPrint(("UDFVVerify: wait for completion\n"));
732 UDFVWaitQueued(VerifyCtx
);
736 } // end UDFVVerify()
743 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
745 if(!VerifyCtx
->VInited
) {
749 KdPrint(("UDFVFlush: wait for completion\n"));
750 UDFVWaitQueued(VerifyCtx
);
752 UDFVVerify(Vcb
, UFD_VERIFY_FLAG_FORCE
);
754 KdPrint(("UDFVFlush: wait for completion (2)\n"));
755 UDFVWaitQueued(VerifyCtx
);
770 BOOLEAN ext_ok
= TRUE
;
772 uint32 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
774 buff
= (uint8
*)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->WriteBlockSize
, 'bNWD' );
776 for(i
=0; i
<BCount
; i
+=d
) {
777 if(!(LBA
+i
& (PS
-1)) &&
785 d
<< Vcb
->BlockSizeBits
,
790 if(RC
!= STATUS_SUCCESS
) {
791 Map
[0].extLocation
= LBA
+i
;
792 Map
[0].extLength
= d
<< Vcb
->BlockSizeBits
;
793 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &(Map
[0]), AS_DISCARDED
| AS_BAD
); // free
800 } // end UDFCheckArea()
803 This routine remaps sectors from bad packet
810 IN BOOLEAN RemapSpared
813 uint32 i
, max
, BS
, orig
;
815 BOOLEAN verified
= FALSE
;
817 if(Vcb
->SparingTable
) {
819 max
= Vcb
->SparingCount
;
820 BS
= Vcb
->SparingBlockSize
;
822 // use sparing table for relocation
823 if(Vcb
->SparingCountFree
== -1) {
824 KdPrint(("calculate free spare areas\n"));
826 KdPrint(("verify spare area\n"));
827 Vcb
->SparingCountFree
= 0;
828 Map
= Vcb
->SparingTable
;
829 for(i
=0;i
<max
;i
++,Map
++) {
830 if(Map
->origLocation
== SPARING_LOC_AVAILABLE
) {
831 if(UDFCheckArea(Vcb
, Map
->mappedLocation
, BS
)) {
832 Vcb
->SparingCountFree
++;
834 KdPrint(("initial check: bad spare block @ %x\n", Map
->mappedLocation
));
835 Map
->origLocation
= SPARING_LOC_CORRUPTED
;
836 Vcb
->SparingTableModified
= TRUE
;
841 if(!Vcb
->SparingCountFree
) {
842 KdPrint(("sparing table full\n"));
843 return STATUS_DISK_FULL
;
846 Map
= Vcb
->SparingTable
;
848 for(i
=0;i
<max
;i
++,Map
++) {
849 orig
= Map
->origLocation
;
850 if(Lba
== (orig
& ~(BS
-1)) ) {
853 KdPrint(("remap remapped: bad spare block @ %x\n", Map
->mappedLocation
));
860 return STATUS_SHARING_VIOLATION
;
862 // look for another remap area
863 Map
->origLocation
= SPARING_LOC_CORRUPTED
;
864 Vcb
->SparingTableModified
= TRUE
;
865 Vcb
->SparingCountFree
--;
870 Map
= Vcb
->SparingTable
;
871 for(i
=0;i
<max
;i
++,Map
++) {
872 if(Map
->origLocation
== SPARING_LOC_AVAILABLE
) {
873 KdPrint(("remap %x -> %x\n", Lba
, Map
->mappedLocation
));
874 Map
->origLocation
= Lba
;
875 Vcb
->SparingTableModified
= TRUE
;
876 Vcb
->SparingCountFree
--;
877 return STATUS_SUCCESS
;
880 KdPrint(("sparing table full\n"));
881 return STATUS_DISK_FULL
;
883 return STATUS_UNSUCCESSFUL
;
884 } // end UDFRemapPacket()
887 This routine releases sector mapping when entire packet is marked as free
897 uint32 i
, max
, BS
, orig
;
900 if(Vcb
->SparingTable
) {
901 // use sparing table for relocation
903 max
= Vcb
->SparingCount
;
904 BS
= Vcb
->SparingBlockSize
;
905 Map
= Vcb
->SparingTable
;
906 for(i
=0;i
<max
;i
++,Map
++) {
907 orig
= Map
->origLocation
;
909 case SPARING_LOC_AVAILABLE
:
910 case SPARING_LOC_CORRUPTED
:
914 (orig
+BS
) <= (Lba
+BCount
)) {
916 KdPrint(("unmap %x -> %x\n", orig
, Map
->mappedLocation
));
917 Map
->origLocation
= SPARING_LOC_AVAILABLE
;
918 Vcb
->SparingTableModified
= TRUE
;
919 Vcb
->SparingCountFree
++;
923 return STATUS_SUCCESS
;
924 } // end UDFUnmapRange()
927 This routine returns physical address for relocated sector
936 uint32 i
, max
, BS
, orig
;
938 if(Vcb
->SparingTable
) {
939 // use sparing table for relocation
941 PSPARING_MAP Map
= Vcb
->SparingTable
;
943 max
= Vcb
->SparingCount
;
944 BS
= Vcb
->SparingBlockSize
;
945 _Lba
= Lba
& ~(BS
-1);
946 for(i
=0;i
<max
;i
++,Map
++) {
947 orig
= Map
->origLocation
;
948 if(_Lba
== (orig
& ~(BS
-1)) ) {
949 //if( (Lba >= (orig = Map->origLocation)) && (Lba < orig + BS) ) {
950 return Map
->mappedLocation
+ Lba
- orig
;
953 } else if(Vcb
->Vat
) {
954 // use VAT for relocation
955 uint32
* Map
= Vcb
->Vat
;
957 // check if given Lba lays in the partition covered by VAT
960 if(Lba
< (root
= Vcb
->Partitions
[Vcb
->VatPartNdx
].PartitionRoot
))
962 Map
= &(Vcb
->Vat
[(i
= Lba
- root
)]);
963 if((i
< Vcb
->VatCount
) && (i
=(*Map
)) ) {
964 if(i
!= UDF_VAT_FREE_ENTRY
) {
972 } // end UDFRelocateSector()
975 This routine checks if the extent specified requires relocation
979 UDFAreSectorsRelocated(
986 if(Vcb
->SparingTable
) {
987 // use sparing table for relocation
989 BS
= Vcb
->SparingBlockSize
;
992 Map
= Vcb
->SparingTable
;
993 for(i
=0;i
<Vcb
->SparingCount
;i
++,Map
++) {
994 if( ((Lba
>= (orig
= Map
->origLocation
)) && (Lba
< orig
+ BS
)) ||
995 ((Lba
+BlockCount
-1 >= orig
) && (Lba
+BlockCount
-1 < orig
+ BS
)) ||
996 ((orig
>= Lba
) && (orig
< Lba
+BlockCount
)) ||
997 ((orig
+BS
>= Lba
) && (orig
+BS
< Lba
+BlockCount
)) ) {
1001 } else if(Vcb
->Vat
) {
1002 // use VAT for relocation
1005 if(Lba
< (root
= Vcb
->Partitions
[Vcb
->VatPartNdx
].PartitionRoot
))
1007 if(Lba
+BlockCount
>= Vcb
->NWA
)
1009 Map
= &(Vcb
->Vat
[Lba
-root
/*+i*/]);
1010 for(i
=0; i
<BlockCount
; i
++, Map
++) {
1012 (j
!= Lba
-root
+i
) &&
1013 ((j
!= UDF_VAT_FREE_ENTRY
) || ((Lba
+i
) < Vcb
->LastLBA
)))
1018 } // end UDFAreSectorsRelocated()
1021 This routine builds mapping for relocated extent
1022 If relocation is not required (-1) will be returned
1029 IN uint32 BlockCount
1032 if(!UDFAreSectorsRelocated(Vcb
, Lba
, BlockCount
)) return UDF_NO_EXTENT_MAP
;
1034 PEXTENT_MAP Extent
=NULL
, Extent2
;
1035 uint32 NewLba
, LastLba
, j
, i
;
1038 LastLba
= UDFRelocateSector(Vcb
, Lba
);
1039 for(i
=0, j
=1; i
<BlockCount
; i
++, j
++) {
1040 // create new entry if the extent in not contigous
1041 if( ((NewLba
= UDFRelocateSector(Vcb
, Lba
+i
+1)) != (LastLba
+1)) ||
1042 (i
==(BlockCount
-1)) ) {
1043 locExt
.extLength
= j
<< Vcb
->BlockSizeBits
;
1044 locExt
.extLocation
= LastLba
-j
+1;
1045 Extent2
= UDFExtentToMapping(&locExt
);
1049 Extent
= UDFMergeMappings(Extent
, Extent2
);
1050 MyFreePool__(Extent2
);
1052 if(!Extent
) return NULL
;
1058 } // end UDFRelocateSectors()