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 disk space management
20 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_REMAP
22 typedef struct _UDF_VERIFY_ITEM
{
28 } UDF_VERIFY_ITEM
, *PUDF_VERIFY_ITEM
;
30 typedef struct _UDF_VERIFY_REQ_RANGE
{
33 } UDF_VERIFY_REQ_RANGE
, *PUDF_VERIFY_REQ_RANGE
;
35 #define MAX_VREQ_RANGES 128
37 typedef struct _UDF_VERIFY_REQ
{
41 UDF_VERIFY_REQ_RANGE vr
[MAX_VREQ_RANGES
];
43 WORK_QUEUE_ITEM VerifyItem
;
45 } UDF_VERIFY_REQ
, *PUDF_VERIFY_REQ
;
49 PUDF_VERIFY_CTX VerifyCtx
,
50 PUDF_VERIFY_ITEM vItem
58 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
60 OSSTATUS status
= STATUS_SUCCESS
;
61 BOOLEAN res_inited
= FALSE
;
63 if(VerifyCtx
->VInited
) {
64 KdPrint(("Already inited\n"));
65 return STATUS_SUCCESS
;
69 RtlZeroMemory(VerifyCtx
, sizeof(UDF_VERIFY_CTX
));
70 if(!Vcb
->VerifyOnWrite
) {
71 KdPrint(("Verify is disabled\n"));
72 return STATUS_SUCCESS
;
75 KdPrint(("Verify is not intended for CD/DVD-R\n"));
76 return STATUS_SUCCESS
;
78 if(!OS_SUCCESS(status
= ExInitializeResourceLite(&(VerifyCtx
->VerifyLock
)))) {
82 VerifyCtx
->ItemCount
= 0;
83 VerifyCtx
->StoredBitMap
= (uint8
*)DbgAllocatePoolWithTag(PagedPool
, (i
= (Vcb
->LastPossibleLBA
+1+7)>>3), 'mNWD' );
84 if(VerifyCtx
->StoredBitMap
) {
85 RtlZeroMemory(VerifyCtx
->StoredBitMap
, i
);
87 KdPrint(("Can't alloc verify bitmap for %x blocks\n", Vcb
->LastPossibleLBA
));
88 try_return(status
= STATUS_INSUFFICIENT_RESOURCES
);
90 InitializeListHead(&(VerifyCtx
->vrfList
));
91 KeInitializeEvent(&(VerifyCtx
->vrfEvent
), SynchronizationEvent
, FALSE
);
92 VerifyCtx
->WaiterCount
= 0;
93 VerifyCtx
->VInited
= TRUE
;
99 if(!OS_SUCCESS(status
)) {
101 ExDeleteResourceLite(&(VerifyCtx
->VerifyLock
));
110 PUDF_VERIFY_CTX VerifyCtx
115 while(VerifyCtx
->QueuedCount
) {
116 KdPrint(("UDFVWaitQueued: wait for completion (%d)\n", VerifyCtx
->QueuedCount
));
117 w
= InterlockedIncrement((PLONG
)&(VerifyCtx
->WaiterCount
));
118 KdPrint((" %d waiters\n", w
));
119 DbgWaitForSingleObject(&(VerifyCtx
->vrfEvent
), NULL
);
120 if(w
= InterlockedDecrement((PLONG
)&(VerifyCtx
->WaiterCount
))) {
121 KdPrint((" still %d waiters, q %d\n", w
, VerifyCtx
->QueuedCount
));
122 if(!VerifyCtx
->QueuedCount
) {
123 KdPrint((" pulse event\n", w
));
124 KeSetEvent(&(VerifyCtx
->vrfEvent
), 0, FALSE
);
129 } // end UDFVWaitQueued()
136 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
138 PUDF_VERIFY_ITEM vItem
;
140 if(!VerifyCtx
->VInited
) {
144 KdPrint(("UDFVRelease: wait for completion\n"));
145 UDFVWaitQueued(VerifyCtx
);
147 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
149 Link
= VerifyCtx
->vrfList
.Flink
;
151 while(Link
!= &(VerifyCtx
->vrfList
)) {
152 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
154 //DbgFreePool(vItem);
155 UDFVRemoveBlock(VerifyCtx
, vItem
);
157 VerifyCtx
->VInited
= FALSE
;
159 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
161 ExDeleteResourceLite(&(VerifyCtx
->VerifyLock
));
162 DbgFreePool(VerifyCtx
->StoredBitMap
);
164 RtlZeroMemory(VerifyCtx
, sizeof(UDF_VERIFY_CTX
));
167 } // end UDFVRelease()
177 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
178 PUDF_VERIFY_ITEM vItem
;
180 KdPrint(("v-add %x\n", LBA
));
182 vItem
= (PUDF_VERIFY_ITEM
)DbgAllocatePoolWithTag(PagedPool
, sizeof(UDF_VERIFY_ITEM
)+Vcb
->BlockSize
, 'bvWD');
185 RtlCopyMemory(vItem
+1, Buffer
, Vcb
->BlockSize
);
187 vItem
->crc
= crc32((PUCHAR
)Buffer
, Vcb
->BlockSize
);
188 vItem
->Buffer
= (PUCHAR
)(vItem
+1);
189 vItem
->queued
= FALSE
;
190 InitializeListHead(&(vItem
->vrfList
));
191 InsertTailList(Link
, &(vItem
->vrfList
));
192 UDFSetBit(VerifyCtx
->StoredBitMap
, LBA
);
193 VerifyCtx
->ItemCount
++;
195 } // end UDFVStoreBlock()
201 PUDF_VERIFY_ITEM vItem
204 KdPrint(("v-upd %x\n", vItem
->lba
));
205 RtlCopyMemory(vItem
+1, Buffer
, Vcb
->BlockSize
);
206 vItem
->crc
= crc32((PUCHAR
)Buffer
, Vcb
->BlockSize
);
208 } // end UDFVUpdateBlock()
212 PUDF_VERIFY_CTX VerifyCtx
,
213 PUDF_VERIFY_ITEM vItem
216 KdPrint(("v-del %x\n", vItem
->lba
));
217 UDFClrBit(VerifyCtx
->StoredBitMap
, vItem
->lba
);
218 RemoveEntryList(&(vItem
->vrfList
));
219 VerifyCtx
->ItemCount
--;
222 } // end UDFVUpdateBlock()
227 IN
void* Buffer
, // Target buffer
230 // OUT uint32* WrittenBytes,
235 PUDF_VERIFY_ITEM vItem
;
236 //PUDF_VERIFY_ITEM vItem1;
237 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
242 if(!VerifyCtx
->VInited
) {
243 return STATUS_SUCCESS
;
246 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
248 for(i
=0, n
=0; i
<BCount
; i
++) {
249 if(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
)) {
250 // some blocks are remembered
258 Link
= VerifyCtx
->vrfList
.Blink
;
259 while(Link
!= &(VerifyCtx
->vrfList
)) {
260 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
262 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
263 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, vItem
->lba
));
264 UDFVUpdateBlock(Vcb
, ((PUCHAR
)Buffer
)+(vItem
->lba
-LBA
)*Vcb
->BlockSize
, vItem
);
275 // find remembered blocks (the 1st one)
276 Link
= VerifyCtx
->vrfList
.Blink
;
277 while(Link
!= &(VerifyCtx
->vrfList
)) {
278 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
280 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
281 //UDFVRemoveBlock(VerifyCtx, vItem);
286 // check if contiguous
288 prev_lba
= vItem
->lba
;
291 while((i
< n
) && (Link
!= &(VerifyCtx
->vrfList
))) {
292 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
294 if(vItem
->lba
> LBA
|| vItem
->lba
>= LBA
+BCount
) {
298 if(vItem
->lba
< prev_lba
) {
302 prev_lba
= vItem
->lba
;
309 // drop all and add again
313 for(i
=0; i
<BCount
; i
++) {
314 if(vItem
->lba
== LBA
+i
) {
315 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
316 UDFVUpdateBlock(Vcb
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, vItem
);
319 if(vItem1
->lba
== LBA
+i
) {
320 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
321 UDFVUpdateBlock(Vcb
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, vItem1
);
324 if(vItem1
->lba
> LBA
+i
) {
325 // just insert this block
326 ASSERT(!UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
327 UDFVStoreBlock(Vcb
, LBA
+i
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, &(vItem1
->vrfList
));
329 vItem
= CONTAINING_RECORD( vItem
->vrfList
.Blink
, UDF_VERIFY_ITEM
, vrfList
);
333 Link
= VerifyCtx
->vrfList
.Blink
;
335 while(Link
!= &(VerifyCtx
->vrfList
)) {
336 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
338 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
339 UDFVRemoveBlock(VerifyCtx
, vItem
);
352 // remember all blocks
353 for(i
=0; i
<BCount
; i
++) {
354 ASSERT(!UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
));
355 UDFVStoreBlock(Vcb
, LBA
+i
, ((PUCHAR
)Buffer
)+i
*Vcb
->BlockSize
, &(VerifyCtx
->vrfList
));
359 if(VerifyCtx
->ItemCount
> UDF_MAX_VERIFY_CACHE
) {
360 UDFVVerify(Vcb
, UFD_VERIFY_FLAG_LOCKED
);
363 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
365 if(VerifyCtx
->ItemCount
> UDF_MAX_VERIFY_CACHE
*2) {
366 //UDFVVerify(Vcb, UFD_VERIFY_FLAG_LOCKED);
367 // TODO: make some delay
370 return STATUS_SUCCESS
;
377 IN
void* Buffer
, // Target buffer
380 // OUT uint32* ReadBytes,
385 PUDF_VERIFY_ITEM vItem
;
386 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
390 OSSTATUS status
= STATUS_SUCCESS
;
393 if(!VerifyCtx
->VInited
) {
394 return STATUS_SUCCESS
;
395 //return STATUS_UNSUCCESSFUL;
398 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
400 for(i
=0, n
=0; i
<BCount
; i
++) {
401 if(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
)) {
402 // some blocks are remembered
408 // no blocks are remembered
409 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
410 return STATUS_SUCCESS
;
413 Link
= VerifyCtx
->vrfList
.Flink
;
415 while(Link
!= &(VerifyCtx
->vrfList
)) {
416 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
418 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
419 ASSERT(UDFGetBit(VerifyCtx
->StoredBitMap
, vItem
->lba
));
421 if(!(Flags
& PH_READ_VERIFY_CACHE
)) {
422 crc
= crc32((PUCHAR
)Buffer
+(vItem
->lba
- LBA
)*Vcb
->BlockSize
, Vcb
->BlockSize
);
423 if(vItem
->crc
!= crc
) {
424 KdPrint(("UDFVRead: stored %x != %x\n", vItem
->crc
, crc
));
425 RtlCopyMemory((PUCHAR
)Buffer
+(vItem
->lba
- LBA
)*Vcb
->BlockSize
, vItem
->Buffer
, Vcb
->BlockSize
);
426 status
= STATUS_FT_WRITE_RECOVERY
;
428 if(!(bm
= (uint32
*)(Vcb
->BSBM_Bitmap
))) {
429 crc
= (Vcb
->LastPossibleLBA
+1+7) >> 3; // reuse 'crc' variable
430 bm
= (uint32
*)(Vcb
->BSBM_Bitmap
= (int8
*)DbgAllocatePoolWithTag(NonPagedPool
, crc
, 'mNWD' ));
432 RtlZeroMemory(bm
, crc
);
434 KdPrint(("Can't alloc BSBM for %x blocks\n", Vcb
->LastPossibleLBA
));
438 UDFSetBit__(bm
, vItem
->lba
);
439 KdPrint(("Set BB @ %#x\n", vItem
->lba
));
442 bm
= (uint32
*)(Vcb
->FSBM_Bitmap
);
444 UDFSetUsedBit(bm
, vItem
->lba
);
445 KdPrint(("Set BB @ %#x as used\n", vItem
->lba
));
447 #endif //_BROWSE_UDF_
452 KdPrint(("UDFVRead: get cached @ %x\n", vItem
->lba
));
453 RtlCopyMemory((PUCHAR
)Buffer
+(vItem
->lba
- LBA
)*Vcb
->BlockSize
, vItem
->Buffer
, Vcb
->BlockSize
);
456 // no more blocks expected
462 if((status
== STATUS_SUCCESS
&& !(Flags
& PH_KEEP_VERIFY_CACHE
)) || (Flags
& PH_FORGET_VERIFIED
)) {
463 // ok, forget this, no errors found
464 Link
= VerifyCtx
->vrfList
.Flink
;
466 while(Link
!= &(VerifyCtx
->vrfList
)) {
467 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
469 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
471 UDFVRemoveBlock(VerifyCtx
, vItem
);
473 // no more blocks expected
480 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
494 PUDF_VERIFY_ITEM vItem
;
495 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
498 OSSTATUS status
= STATUS_SUCCESS
;
500 if(!VerifyCtx
->VInited
) {
501 return STATUS_UNSUCCESSFUL
;
504 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
506 for(i
=0, n
=0; i
<BCount
; i
++) {
507 if(UDFGetBit(VerifyCtx
->StoredBitMap
, LBA
+i
)) {
508 // some blocks are remembered
514 // no blocks are remembered
515 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
516 return STATUS_SUCCESS
;
519 Link
= VerifyCtx
->vrfList
.Flink
;
521 while(Link
!= &(VerifyCtx
->vrfList
)) {
522 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
524 if(vItem
->lba
>= LBA
&& vItem
->lba
< LBA
+BCount
) {
526 UDFVRemoveBlock(VerifyCtx
, vItem
);
528 // no more blocks expected
534 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
537 } // end UDFVForget()
541 PUDF_VERIFY_REQ VerifyReq
544 PVCB Vcb
= VerifyReq
->Vcb
;
549 ReadBytes
= (ULONG
)Vcb
;
551 if(Vcb
->SparingCountFree
) {
552 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
);
553 for(i
=0; i
<VerifyReq
->nReq
; i
++) {
554 RC
= UDFTIOVerify(Vcb
,
555 VerifyReq
->Buffer
, // Target buffer
556 VerifyReq
->vr
[i
].BCount
<< Vcb
->BlockSizeBits
,
557 VerifyReq
->vr
[i
].lba
,
559 PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
/*| PH_LOCK_CACHE*/);
561 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
563 for(i
=0; i
<VerifyReq
->nReq
; i
++) {
564 KdPrint(("!!! No more space for remap !!!\n"));
565 KdPrint((" try del from verify cache @ %x\n", VerifyReq
->vr
[i
].lba
));
566 RC
= UDFVRead(Vcb
, VerifyReq
->Buffer
, VerifyReq
->vr
[i
].BCount
, VerifyReq
->vr
[i
].lba
,
567 PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
);
571 for(i
=0; i
<VerifyReq
->nReq
; i
++) {
572 if(Vcb
->SparingCountFree
) {
573 WCacheStartDirect__(&(Vcb
->FastCache
), Vcb
, TRUE
);
574 RC
= UDFTIOVerify(Vcb
,
575 VerifyReq
->Buffer
, // Target buffer
576 VerifyReq
->vr
[i
].BCount
<< Vcb
->BlockSizeBits
,
577 VerifyReq
->vr
[i
].lba
,
579 PH_TMP_BUFFER
| PH_VCB_IN_RETLEN
/*| PH_LOCK_CACHE*/);
580 WCacheEODirect__(&(Vcb
->FastCache
), Vcb
);
582 KdPrint(("!!! No more space for remap !!!\n"));
583 KdPrint((" try del from verify cache @ %x\n", VerifyReq
->vr
[i
].lba
));
584 RC
= UDFVRead(Vcb
, VerifyReq
->Buffer
, VerifyReq
->vr
[i
].BCount
, VerifyReq
->vr
[i
].lba
,
585 PH_FORGET_VERIFIED
| PH_READ_VERIFY_CACHE
| PH_TMP_BUFFER
);
589 DbgFreePool(VerifyReq
->Buffer
);
590 DbgFreePool(VerifyReq
);
591 InterlockedDecrement((PLONG
)&(Vcb
->VerifyCtx
.QueuedCount
));
592 KdPrint((" QueuedCount = %d\n", Vcb
->VerifyCtx
.QueuedCount
));
593 KdPrint((" Setting event...\n"));
594 KeSetEvent(&(Vcb
->VerifyCtx
.vrfEvent
), 0, FALSE
);
596 } // end UDFVWorkItem()
604 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
606 PUDF_VERIFY_ITEM vItem
;
607 PUDF_VERIFY_REQ VerifyReq
= NULL
;
608 ULONG len
, max_len
=0;
612 BOOLEAN do_vrf
= FALSE
;
614 if(!VerifyCtx
->VInited
) {
617 if(VerifyCtx
->QueuedCount
) {
618 if(Flags
& UFD_VERIFY_FLAG_WAIT
) {
619 KdPrint((" wait for verify flush\n"));
622 KdPrint((" verify flush already queued\n"));
626 if(!(Flags
& (UFD_VERIFY_FLAG_FORCE
| UFD_VERIFY_FLAG_BG
))) {
627 if(VerifyCtx
->ItemCount
< UDF_MAX_VERIFY_CACHE
) {
632 if(!(Flags
& UFD_VERIFY_FLAG_LOCKED
)) {
633 UDFAcquireResourceExclusive(&(VerifyCtx
->VerifyLock
), TRUE
);
636 if(Flags
& UFD_VERIFY_FLAG_FORCE
) {
637 i
= VerifyCtx
->ItemCount
;
639 if(VerifyCtx
->ItemCount
>= UDF_MAX_VERIFY_CACHE
) {
640 i
= VerifyCtx
->ItemCount
- UDF_VERIFY_CACHE_LOW
;
642 i
= min(UDF_VERIFY_CACHE_GRAN
, VerifyCtx
->ItemCount
);
646 Link
= VerifyCtx
->vrfList
.Flink
;
651 ASSERT(Link
!= &(VerifyCtx
->vrfList
));
653 if(Link == &(VerifyCtx->vrfList)) {
660 vItem
= CONTAINING_RECORD( Link
, UDF_VERIFY_ITEM
, vrfList
);
664 if(!vItem
->queued
&& (prev_lba
+len
== vItem
->lba
)) {
665 vItem
->queued
= TRUE
;
672 prev_lba
= vItem
->lba
;
675 if((i
== 1) && len
) {
684 VerifyReq
= (PUDF_VERIFY_REQ
)DbgAllocatePoolWithTag(NonPagedPool
, sizeof(UDF_VERIFY_REQ
), 'bNWD');
686 RtlZeroMemory(VerifyReq
, sizeof(UDF_VERIFY_REQ
));
687 VerifyReq
->Vcb
= Vcb
;
692 VerifyReq
->vr
[VerifyReq
->nReq
].lba
= prev_lba
;
693 VerifyReq
->vr
[VerifyReq
->nReq
].BCount
= len
;
699 if((VerifyReq
->nReq
>= MAX_VREQ_RANGES
) || (i
== 1)) {
701 VerifyReq
->Buffer
= (PUCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, max_len
* Vcb
->BlockSize
, 'bNWD');
702 if(VerifyReq
->Buffer
) {
703 InterlockedIncrement((PLONG
)&(VerifyCtx
->QueuedCount
));
705 ExInitializeWorkItem( &(VerifyReq
->VerifyItem
),
706 (PWORKER_THREAD_ROUTINE
) UDFVWorkItem
,
708 ExQueueWorkItem( &(VerifyReq
->VerifyItem
), CriticalWorkQueue
);
710 UDFVWorkItem(VerifyReq
);
713 DbgFreePool(VerifyReq
);
721 prev_lba
= vItem
->lba
;
727 if(!(Flags
& UFD_VERIFY_FLAG_LOCKED
)) {
728 UDFReleaseResource(&(VerifyCtx
->VerifyLock
));
730 if(Flags
& UFD_VERIFY_FLAG_WAIT
) {
732 KdPrint(("UDFVVerify: wait for completion\n"));
733 UDFVWaitQueued(VerifyCtx
);
737 } // end UDFVVerify()
744 PUDF_VERIFY_CTX VerifyCtx
= &Vcb
->VerifyCtx
;
746 if(!VerifyCtx
->VInited
) {
750 KdPrint(("UDFVFlush: wait for completion\n"));
751 UDFVWaitQueued(VerifyCtx
);
753 UDFVVerify(Vcb
, UFD_VERIFY_FLAG_FORCE
);
755 KdPrint(("UDFVFlush: wait for completion (2)\n"));
756 UDFVWaitQueued(VerifyCtx
);
771 BOOLEAN ext_ok
= TRUE
;
773 uint32 PS
= Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
;
775 buff
= (uint8
*)DbgAllocatePoolWithTag(NonPagedPool
, Vcb
->WriteBlockSize
, 'bNWD' );
777 for(i
=0; i
<BCount
; i
+=d
) {
778 if(!(LBA
+i
& (PS
-1)) &&
786 d
<< Vcb
->BlockSizeBits
,
791 if(RC
!= STATUS_SUCCESS
) {
792 Map
[0].extLocation
= LBA
+i
;
793 Map
[0].extLength
= d
<< Vcb
->BlockSizeBits
;
794 UDFMarkSpaceAsXXXNoProtect(Vcb
, 0, &(Map
[0]), AS_DISCARDED
| AS_BAD
); // free
801 } // end UDFCheckArea()
804 This routine remaps sectors from bad packet
811 IN BOOLEAN RemapSpared
814 uint32 i
, max
, BS
, orig
;
816 BOOLEAN verified
= FALSE
;
818 if(Vcb
->SparingTable
) {
820 max
= Vcb
->SparingCount
;
821 BS
= Vcb
->SparingBlockSize
;
823 // use sparing table for relocation
824 if(Vcb
->SparingCountFree
== -1) {
825 KdPrint(("calculate free spare areas\n"));
827 KdPrint(("verify spare area\n"));
828 Vcb
->SparingCountFree
= 0;
829 Map
= Vcb
->SparingTable
;
830 for(i
=0;i
<max
;i
++,Map
++) {
831 if(Map
->origLocation
== SPARING_LOC_AVAILABLE
) {
832 if(UDFCheckArea(Vcb
, Map
->mappedLocation
, BS
)) {
833 Vcb
->SparingCountFree
++;
835 KdPrint(("initial check: bad spare block @ %x\n", Map
->mappedLocation
));
836 Map
->origLocation
= SPARING_LOC_CORRUPTED
;
837 Vcb
->SparingTableModified
= TRUE
;
842 if(!Vcb
->SparingCountFree
) {
843 KdPrint(("sparing table full\n"));
844 return STATUS_DISK_FULL
;
847 Map
= Vcb
->SparingTable
;
849 for(i
=0;i
<max
;i
++,Map
++) {
850 orig
= Map
->origLocation
;
851 if(Lba
== (orig
& ~(BS
-1)) ) {
854 KdPrint(("remap remapped: bad spare block @ %x\n", Map
->mappedLocation
));
861 return STATUS_SHARING_VIOLATION
;
863 // look for another remap area
864 Map
->origLocation
= SPARING_LOC_CORRUPTED
;
865 Vcb
->SparingTableModified
= TRUE
;
866 Vcb
->SparingCountFree
--;
871 Map
= Vcb
->SparingTable
;
872 for(i
=0;i
<max
;i
++,Map
++) {
873 if(Map
->origLocation
== SPARING_LOC_AVAILABLE
) {
874 KdPrint(("remap %x -> %x\n", Lba
, Map
->mappedLocation
));
875 Map
->origLocation
= Lba
;
876 Vcb
->SparingTableModified
= TRUE
;
877 Vcb
->SparingCountFree
--;
878 return STATUS_SUCCESS
;
881 KdPrint(("sparing table full\n"));
882 return STATUS_DISK_FULL
;
884 return STATUS_UNSUCCESSFUL
;
885 } // end UDFRemapPacket()
888 This routine releases sector mapping when entire packet is marked as free
898 uint32 i
, max
, BS
, orig
;
901 if(Vcb
->SparingTable
) {
902 // use sparing table for relocation
904 max
= Vcb
->SparingCount
;
905 BS
= Vcb
->SparingBlockSize
;
906 Map
= Vcb
->SparingTable
;
907 for(i
=0;i
<max
;i
++,Map
++) {
908 orig
= Map
->origLocation
;
910 case SPARING_LOC_AVAILABLE
:
911 case SPARING_LOC_CORRUPTED
:
915 (orig
+BS
) <= (Lba
+BCount
)) {
917 KdPrint(("unmap %x -> %x\n", orig
, Map
->mappedLocation
));
918 Map
->origLocation
= SPARING_LOC_AVAILABLE
;
919 Vcb
->SparingTableModified
= TRUE
;
920 Vcb
->SparingCountFree
++;
924 return STATUS_SUCCESS
;
925 } // end UDFUnmapRange()
928 This routine returns physical address for relocated sector
937 uint32 i
, max
, BS
, orig
;
939 if(Vcb
->SparingTable
) {
940 // use sparing table for relocation
942 PSPARING_MAP Map
= Vcb
->SparingTable
;
944 max
= Vcb
->SparingCount
;
945 BS
= Vcb
->SparingBlockSize
;
946 _Lba
= Lba
& ~(BS
-1);
947 for(i
=0;i
<max
;i
++,Map
++) {
948 orig
= Map
->origLocation
;
949 if(_Lba
== (orig
& ~(BS
-1)) ) {
950 //if( (Lba >= (orig = Map->origLocation)) && (Lba < orig + BS) ) {
951 return Map
->mappedLocation
+ Lba
- orig
;
954 } else if(Vcb
->Vat
) {
955 // use VAT for relocation
956 uint32
* Map
= Vcb
->Vat
;
958 // check if given Lba lays in the partition covered by VAT
961 if(Lba
< (root
= Vcb
->Partitions
[Vcb
->VatPartNdx
].PartitionRoot
))
963 Map
= &(Vcb
->Vat
[(i
= Lba
- root
)]);
964 if((i
< Vcb
->VatCount
) && (i
=(*Map
)) ) {
965 if(i
!= UDF_VAT_FREE_ENTRY
) {
973 } // end UDFRelocateSector()
976 This routine checks if the extent specified requires relocation
980 UDFAreSectorsRelocated(
987 if(Vcb
->SparingTable
) {
988 // use sparing table for relocation
990 BS
= Vcb
->SparingBlockSize
;
993 Map
= Vcb
->SparingTable
;
994 for(i
=0;i
<Vcb
->SparingCount
;i
++,Map
++) {
995 if( ((Lba
>= (orig
= Map
->origLocation
)) && (Lba
< orig
+ BS
)) ||
996 ((Lba
+BlockCount
-1 >= orig
) && (Lba
+BlockCount
-1 < orig
+ BS
)) ||
997 ((orig
>= Lba
) && (orig
< Lba
+BlockCount
)) ||
998 ((orig
+BS
>= Lba
) && (orig
+BS
< Lba
+BlockCount
)) ) {
1002 } else if(Vcb
->Vat
) {
1003 // use VAT for relocation
1006 if(Lba
< (root
= Vcb
->Partitions
[Vcb
->VatPartNdx
].PartitionRoot
))
1008 if(Lba
+BlockCount
>= Vcb
->NWA
)
1010 Map
= &(Vcb
->Vat
[Lba
-root
/*+i*/]);
1011 for(i
=0; i
<BlockCount
; i
++, Map
++) {
1013 (j
!= Lba
-root
+i
) &&
1014 ((j
!= UDF_VAT_FREE_ENTRY
) || ((Lba
+i
) < Vcb
->LastLBA
)))
1019 } // end UDFAreSectorsRelocated()
1022 This routine builds mapping for relocated extent
1023 If relocation is not required (-1) will be returned
1030 IN uint32 BlockCount
1033 if(!UDFAreSectorsRelocated(Vcb
, Lba
, BlockCount
)) return UDF_NO_EXTENT_MAP
;
1035 PEXTENT_MAP Extent
=NULL
, Extent2
;
1036 uint32 NewLba
, LastLba
, j
, i
;
1039 LastLba
= UDFRelocateSector(Vcb
, Lba
);
1040 for(i
=0, j
=1; i
<BlockCount
; i
++, j
++) {
1041 // create new entry if the extent in not contigous
1042 if( ((NewLba
= UDFRelocateSector(Vcb
, Lba
+i
+1)) != (LastLba
+1)) ||
1043 (i
==(BlockCount
-1)) ) {
1044 locExt
.extLength
= j
<< Vcb
->BlockSizeBits
;
1045 locExt
.extLocation
= LastLba
-j
+1;
1046 Extent2
= UDFExtentToMapping(&locExt
);
1050 Extent
= UDFMergeMappings(Extent
, Extent2
);
1051 MyFreePool__(Extent2
);
1053 if(!Extent
) return NULL
;
1059 } // end UDFRelocateSectors()