2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/largemcb.c
5 * PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Pierre Schweitzer (heis_spiter@hotmail.com)
8 * Art Yerkes (art.yerkes@gmail.com)
11 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList
;
20 NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList
;
22 typedef struct _LARGE_MCB_MAPPING_ENTRY
24 LARGE_INTEGER RunStartVbn
;
25 LARGE_INTEGER SectorCount
;
26 LARGE_INTEGER StartingLbn
;
28 } LARGE_MCB_MAPPING_ENTRY
, *PLARGE_MCB_MAPPING_ENTRY
;
30 typedef struct _LARGE_MCB_MAPPING
32 RTL_GENERIC_TABLE Table
;
33 LIST_ENTRY SequenceList
;
34 } LARGE_MCB_MAPPING
, *PLARGE_MCB_MAPPING
;
36 typedef struct _BASE_MCB_INTERNAL
{
37 ULONG MaximumPairCount
;
41 PLARGE_MCB_MAPPING Mapping
;
42 } BASE_MCB_INTERNAL
, *PBASE_MCB_INTERNAL
;
45 static PVOID NTAPI
McbMappingAllocate(PRTL_GENERIC_TABLE Table
, CLONG Bytes
)
48 PBASE_MCB Mcb
= (PBASE_MCB
)Table
->TableContext
;
49 Result
= ExAllocatePoolWithTag(Mcb
->PoolType
, Bytes
, 'LMCB');
50 DPRINT("McbMappingAllocate(%d) => %p\n", Bytes
, Result
);
54 static VOID NTAPI
McbMappingFree(PRTL_GENERIC_TABLE Table
, PVOID Buffer
)
56 DPRINT("McbMappingFree(%p)\n", Buffer
);
57 ExFreePoolWithTag(Buffer
, 'LMCB');
60 static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingCompare
61 (RTL_GENERIC_TABLE Table
, PVOID PtrA
, PVOID PtrB
)
63 PLARGE_MCB_MAPPING_ENTRY A
= PtrA
, B
= PtrB
;
66 (A
->RunStartVbn
.QuadPart
+ A
->SectorCount
.QuadPart
< B
->RunStartVbn
.QuadPart
) ? GenericLessThan
:
67 (A
->RunStartVbn
.QuadPart
> B
->RunStartVbn
.QuadPart
+ B
->SectorCount
.QuadPart
) ? GenericGreaterThan
: GenericEqual
;
70 /* PUBLIC FUNCTIONS **********************************************************/
77 FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb
,
80 IN LONGLONG SectorCount
)
82 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
83 LARGE_MCB_MAPPING_ENTRY Node
;
84 PLARGE_MCB_MAPPING_ENTRY Existing
= NULL
;
85 BOOLEAN NewElement
= FALSE
;
87 Node
.RunStartVbn
.QuadPart
= Vbn
;
88 Node
.StartingLbn
.QuadPart
= Lbn
;
89 Node
.SectorCount
.QuadPart
= SectorCount
;
93 DPRINT("Inserting %x:%x\n", Node
.RunStartVbn
.LowPart
, Node
.SectorCount
.LowPart
);
94 Existing
= RtlInsertElementGenericTable(&Mcb
->Mapping
->Table
, &Node
, sizeof(Node
), &NewElement
);
95 DPRINT("Existing %x\n", Existing
);
98 DPRINT("NewElement %d\n", NewElement
);
101 // We merge the existing runs
102 LARGE_INTEGER StartVbn
, FinalVbn
;
103 DPRINT("Existing: %x:%x\n", Existing
->RunStartVbn
.LowPart
, Node
.SectorCount
.LowPart
);
104 if (Existing
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
)
106 StartVbn
= Existing
->RunStartVbn
;
107 Node
.StartingLbn
= Existing
->StartingLbn
;
111 StartVbn
= Node
.RunStartVbn
;
113 DPRINT("StartVbn %x\n", StartVbn
.LowPart
);
114 if (Existing
->RunStartVbn
.QuadPart
+ Existing
->SectorCount
.QuadPart
>
115 Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
)
117 FinalVbn
.QuadPart
= Existing
->RunStartVbn
.QuadPart
+ Existing
->SectorCount
.QuadPart
;
121 FinalVbn
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
;
123 DPRINT("FinalVbn %x\n", FinalVbn
.LowPart
);
124 Node
.RunStartVbn
.QuadPart
= StartVbn
.QuadPart
;
125 Node
.SectorCount
.QuadPart
= FinalVbn
.QuadPart
- StartVbn
.QuadPart
;
126 RemoveHeadList(&Existing
->Sequence
);
127 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Existing
);
132 DPRINT("Mapping added %x\n", Existing
);
133 Mcb
->MaximumPairCount
++;
135 InsertHeadList(&Mcb
->Mapping
->SequenceList
, &Existing
->Sequence
);
139 DPRINT("!!Existing %d\n", !!Existing
);
148 FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb
,
151 IN LONGLONG SectorCount
)
155 DPRINT("Mcb %x Vbn %x Lbn %x SectorCount %x\n", Mcb
, Vbn
, Lbn
, SectorCount
);
157 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
158 Result
= FsRtlAddBaseMcbEntry(&(Mcb
->BaseMcb
),
162 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
164 DPRINT("Done %d\n", Result
);
174 FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb
,
178 OUT PLONGLONG SectorCount
)
180 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
182 BOOLEAN Result
= FALSE
;
183 PLARGE_MCB_MAPPING_ENTRY Entry
;
185 for (Entry
= (PLARGE_MCB_MAPPING_ENTRY
)RtlEnumerateGenericTable(&Mcb
->Mapping
->Table
, TRUE
);
186 Entry
&& (i
< RunIndex
);
187 Entry
= (PLARGE_MCB_MAPPING_ENTRY
)RtlEnumerateGenericTable(&Mcb
->Mapping
->Table
, FALSE
), i
++);
193 *Vbn
= Entry
->RunStartVbn
.QuadPart
;
195 *Lbn
= Entry
->StartingLbn
.QuadPart
;
197 *SectorCount
= Entry
->SectorCount
.QuadPart
;
208 FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb
,
212 OUT PLONGLONG SectorCount
)
216 DPRINT("FsRtlGetNextLargeMcbEntry Mcb %x RunIndex %x\n", Mcb
, RunIndex
);
218 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
219 Result
= FsRtlGetNextBaseMcbEntry(&(Mcb
->BaseMcb
),
224 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
226 DPRINT("Done %d\n", Result
);
236 FsRtlInitializeBaseMcb(IN PBASE_MCB OpaqueMcb
,
237 IN POOL_TYPE PoolType
)
239 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
242 if (PoolType
== PagedPool
)
244 Mcb
->Mapping
= ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList
);
248 Mcb
->Mapping
= ExAllocatePoolWithTag(PoolType
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
249 sizeof(LARGE_MCB_MAPPING
),
253 Mcb
->PoolType
= PoolType
;
254 Mcb
->MaximumPairCount
= MAXIMUM_PAIR_COUNT
;
255 RtlInitializeGenericTable(&Mcb
->Mapping
->Table
,
256 (PRTL_GENERIC_COMPARE_ROUTINE
)McbMappingCompare
,
260 InitializeListHead(&Mcb
->Mapping
->SequenceList
);
268 FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb
,
269 IN POOL_TYPE PoolType
)
271 Mcb
->GuardedMutex
= ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList
);
273 KeInitializeGuardedMutex(Mcb
->GuardedMutex
);
277 FsRtlInitializeBaseMcb(&(Mcb
->BaseMcb
), PoolType
);
279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
281 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList
,
283 Mcb
->GuardedMutex
= NULL
;
293 FsRtlInitializeLargeMcbs(VOID
)
295 /* Initialize the list for the MCB */
296 ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList
,
299 POOL_RAISE_IF_ALLOCATION_FAILURE
,
300 sizeof(LARGE_MCB_MAPPING
),
302 0); /* FIXME: Should be 4 */
304 /* Initialize the list for the guarded mutex */
305 ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList
,
308 POOL_RAISE_IF_ALLOCATION_FAILURE
,
309 sizeof(KGUARDED_MUTEX
),
311 0); /* FIXME: Should be 32 */
319 FsRtlLookupBaseMcbEntry(IN PBASE_MCB OpaqueMcb
,
321 OUT PLONGLONG Lbn OPTIONAL
,
322 OUT PLONGLONG SectorCountFromLbn OPTIONAL
,
323 OUT PLONGLONG StartingLbn OPTIONAL
,
324 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL
,
325 OUT PULONG Index OPTIONAL
)
327 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
328 BOOLEAN Result
= FALSE
;
329 LARGE_MCB_MAPPING_ENTRY ToLookup
;
330 PLARGE_MCB_MAPPING_ENTRY Entry
;
332 ToLookup
.RunStartVbn
.QuadPart
= Vbn
;
333 ToLookup
.SectorCount
.QuadPart
= 1;
335 Entry
= RtlLookupElementGenericTable(&Mcb
->Mapping
->Table
, &ToLookup
);
336 DPRINT("Entry %p\n", Entry
);
339 // Find out if we have a following entry. The spec says we should return
340 // found with Lbn == -1 when we're beneath the largest map.
341 ToLookup
.SectorCount
.QuadPart
= (1ull<<62) - ToLookup
.RunStartVbn
.QuadPart
;
342 Entry
= RtlLookupElementGenericTable(&Mcb
->Mapping
->Table
, &ToLookup
);
343 DPRINT("Entry %p\n", Entry
);
347 if (Lbn
) *Lbn
= ~0ull;
356 LARGE_INTEGER Offset
;
357 Offset
.QuadPart
= Vbn
- Entry
->RunStartVbn
.QuadPart
;
359 if (Lbn
) *Lbn
= Entry
->StartingLbn
.QuadPart
+ Offset
.QuadPart
;
360 if (SectorCountFromLbn
) *SectorCountFromLbn
= Entry
->SectorCount
.QuadPart
- Offset
.QuadPart
;
361 if (StartingLbn
) *StartingLbn
= Entry
->StartingLbn
.QuadPart
;
362 if (SectorCountFromStartingLbn
) *SectorCountFromStartingLbn
= Entry
->SectorCount
.QuadPart
;
373 FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb
,
375 OUT PLONGLONG Lbn OPTIONAL
,
376 OUT PLONGLONG SectorCountFromLbn OPTIONAL
,
377 OUT PLONGLONG StartingLbn OPTIONAL
,
378 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL
,
379 OUT PULONG Index OPTIONAL
)
383 DPRINT("FsRtlLookupLargeMcbEntry Mcb %x Vbn %x\n", Mcb
, (ULONG
)Vbn
);
385 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
386 Result
= FsRtlLookupBaseMcbEntry(&(Mcb
->BaseMcb
),
391 SectorCountFromStartingLbn
,
393 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
395 DPRINT("Done %d\n", Result
);
405 FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb
,
406 IN OUT PLONGLONG LargeVbn
,
407 IN OUT PLONGLONG LargeLbn
,
410 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
412 BOOLEAN Result
= FALSE
;
413 PLIST_ENTRY ListEntry
;
414 PLARGE_MCB_MAPPING_ENTRY Entry
;
415 PLARGE_MCB_MAPPING_ENTRY CountEntry
;
417 ListEntry
= &Mcb
->Mapping
->SequenceList
;
418 if (!IsListEmpty(ListEntry
))
420 Entry
= CONTAINING_RECORD(ListEntry
->Flink
, LARGE_MCB_MAPPING_ENTRY
, Sequence
);
422 *LargeVbn
= Entry
->RunStartVbn
.QuadPart
;
423 *LargeLbn
= Entry
->StartingLbn
.QuadPart
;
425 for (i
= 0, CountEntry
= RtlEnumerateGenericTable(&Mcb
->Mapping
->Table
, TRUE
);
427 CountEntry
= RtlEnumerateGenericTable(&Mcb
->Mapping
->Table
, FALSE
));
428 DPRINT1("Most probably we are returning shit now\n");
440 FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb
,
441 OUT PLONGLONG LargeVbn
,
442 OUT PLONGLONG LargeLbn
,
447 DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex %x\n", OpaqueMcb
);
449 KeAcquireGuardedMutex(OpaqueMcb
->GuardedMutex
);
450 Result
= FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb
->BaseMcb
),
454 KeReleaseGuardedMutex(OpaqueMcb
->GuardedMutex
);
456 DPRINT("Done %d\n", Result
);
466 FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB OpaqueMcb
,
470 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
471 BOOLEAN Result
= FALSE
;
472 PLIST_ENTRY ListEntry
;
473 PLARGE_MCB_MAPPING_ENTRY Entry
;
475 ListEntry
= &Mcb
->Mapping
->SequenceList
;
476 if (!IsListEmpty(ListEntry
))
478 Entry
= CONTAINING_RECORD(ListEntry
->Flink
, LARGE_MCB_MAPPING_ENTRY
, Sequence
);
480 *Vbn
= Entry
->RunStartVbn
.QuadPart
;
481 *Lbn
= Entry
->StartingLbn
.QuadPart
;
492 FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb
,
498 DPRINT("FsRtlLookupLastLargeMcbEntry Mcb %x\n", Mcb
);
500 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
501 Result
= FsRtlLookupLastBaseMcbEntry(&(Mcb
->BaseMcb
),
504 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
506 DPRINT("Done %d\n", Result
);
516 FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB Mcb
)
518 /* Return the count */
519 return Mcb
->PairCount
;
527 FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb
)
531 DPRINT("FsRtlNumberOfRunsInLargeMcb Mcb %x\n", Mcb
);
533 /* Read the number of runs while holding the MCB lock */
534 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
535 NumberOfRuns
= Mcb
->BaseMcb
.PairCount
;
536 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
538 DPRINT("Done %d\n", NumberOfRuns
);
540 /* Return the count */
549 FsRtlRemoveBaseMcbEntry(IN PBASE_MCB OpaqueMcb
,
551 IN LONGLONG SectorCount
)
553 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
554 LARGE_MCB_MAPPING_ENTRY Node
;
555 LARGE_MCB_MAPPING_ENTRY NewElement
;
556 PLARGE_MCB_MAPPING_ENTRY Element
;
557 PLARGE_MCB_MAPPING_ENTRY Reinserted
, Inserted
;
558 LARGE_INTEGER StartHole
, EndHole
, EndRun
;
560 Node
.RunStartVbn
.QuadPart
= Vbn
;
561 Node
.SectorCount
.QuadPart
= SectorCount
;
563 while ((Element
= RtlLookupElementGenericTable(&Mcb
->Mapping
->Table
, &Node
)))
565 DPRINT1("Node.RunStartVbn %I64d, Node.SectorCount %I64d\n", Node
.RunStartVbn
.QuadPart
, Node
.SectorCount
.QuadPart
);
566 DPRINT1("Element %p, .RunStartVbn %I64d, .SectorCount %I64d\n", Element
, Element
->RunStartVbn
.QuadPart
, Element
->SectorCount
.QuadPart
);
568 if (Element
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
&&
569 Element
->SectorCount
.QuadPart
> Node
.SectorCount
.QuadPart
)
571 LARGE_MCB_MAPPING_ENTRY Upper
, Reinsert
;
572 StartHole
= Node
.RunStartVbn
;
573 EndHole
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
;
575 Upper
.RunStartVbn
.QuadPart
= EndHole
.QuadPart
;
576 Upper
.StartingLbn
.QuadPart
= Element
->StartingLbn
.QuadPart
+ EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
;
577 Upper
.SectorCount
.QuadPart
= Element
->SectorCount
.QuadPart
- (EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
);
579 Reinsert
.SectorCount
.QuadPart
= Element
->RunStartVbn
.QuadPart
- StartHole
.QuadPart
;
580 RemoveEntryList(&Element
->Sequence
);
581 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Element
);
584 Reinserted
= RtlInsertElementGenericTable(&Mcb
->Mapping
->Table
, &Reinsert
, sizeof(Reinsert
), NULL
);
585 InsertHeadList(&Mcb
->Mapping
->SequenceList
, &Reinserted
->Sequence
);
588 Inserted
= RtlInsertElementGenericTable(&Mcb
->Mapping
->Table
, &Upper
, sizeof(Upper
), NULL
);
589 InsertHeadList(&Mcb
->Mapping
->SequenceList
, &Inserted
->Sequence
);
592 else if (Element
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
)
594 StartHole
= Node
.RunStartVbn
;
595 NewElement
.RunStartVbn
= Element
->RunStartVbn
;
596 NewElement
.StartingLbn
= Element
->StartingLbn
;
597 NewElement
.SectorCount
.QuadPart
= StartHole
.QuadPart
- Element
->StartingLbn
.QuadPart
;
599 RemoveEntryList(&Element
->Sequence
);
600 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Element
);
603 Reinserted
= RtlInsertElementGenericTable(&Mcb
->Mapping
->Table
, &NewElement
, sizeof(NewElement
), NULL
);
604 InsertHeadList(&Mcb
->Mapping
->SequenceList
, &Reinserted
->Sequence
);
609 EndHole
= Element
->RunStartVbn
;
610 EndRun
.QuadPart
= Element
->RunStartVbn
.QuadPart
+ Element
->SectorCount
.QuadPart
;
611 NewElement
.RunStartVbn
= EndHole
;
612 NewElement
.StartingLbn
.QuadPart
= Element
->StartingLbn
.QuadPart
+ (EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
);
613 NewElement
.SectorCount
.QuadPart
= EndRun
.QuadPart
- EndHole
.QuadPart
;
615 RemoveEntryList(&Element
->Sequence
);
616 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Element
);
619 Reinserted
= RtlInsertElementGenericTable(&Mcb
->Mapping
->Table
, &NewElement
, sizeof(NewElement
), NULL
);
620 InsertHeadList(&Mcb
->Mapping
->SequenceList
, &Reinserted
->Sequence
);
623 DPRINT1("Reinserted %p, .RunStartVbn %I64d, .SectorCount %I64d\n", Reinserted
, Reinserted
->RunStartVbn
.QuadPart
, Reinserted
->SectorCount
.QuadPart
);
624 DPRINT1("NewElement .RunStartVbn %I64d, .SectorCount %I64d\n", NewElement
.RunStartVbn
.QuadPart
, NewElement
.SectorCount
.QuadPart
);
636 FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb
,
638 IN LONGLONG SectorCount
)
640 DPRINT("FsRtlRemoveLargeMcbEntry Mcb %x, Vbn %I64d, SectorCount %I64d\n", Mcb
, (ULONG
)Vbn
, (ULONG
)SectorCount
);
642 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
643 FsRtlRemoveBaseMcbEntry(&(Mcb
->BaseMcb
), Vbn
, SectorCount
);
644 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
654 FsRtlResetBaseMcb(IN PBASE_MCB OpaqueMcb
)
656 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
657 PLARGE_MCB_MAPPING_ENTRY Element
;
659 while (RtlNumberGenericTableElements(&Mcb
->Mapping
->Table
) &&
660 (Element
= (PLARGE_MCB_MAPPING_ENTRY
)RtlGetElementGenericTable(&Mcb
->Mapping
->Table
, 0)))
662 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Element
);
666 Mcb
->MaximumPairCount
= 0;
674 FsRtlResetLargeMcb(IN PLARGE_MCB Mcb
,
675 IN BOOLEAN SelfSynchronized
)
677 if (!SelfSynchronized
)
678 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
680 FsRtlResetBaseMcb(&Mcb
->BaseMcb
);
682 if (!SelfSynchronized
)
683 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
686 #define MCB_BUMP_NO_MORE 0
687 #define MCB_BUMP_AGAIN 1
689 static ULONG NTAPI
McbBump(PBASE_MCB_INTERNAL Mcb
, PLARGE_MCB_MAPPING_ENTRY FixedPart
)
691 LARGE_MCB_MAPPING_ENTRY Reimagined
;
692 PLARGE_MCB_MAPPING_ENTRY Found
= NULL
;
694 DPRINT("McbBump %x (%x:%x)\n", Mcb
, FixedPart
->RunStartVbn
.LowPart
, FixedPart
->SectorCount
.LowPart
);
696 Reimagined
= *FixedPart
;
697 while ((Found
= RtlLookupElementGenericTable(&Mcb
->Mapping
->Table
, &Reimagined
)))
700 Reimagined
.RunStartVbn
.QuadPart
=
701 FixedPart
->RunStartVbn
.QuadPart
+ FixedPart
->SectorCount
.QuadPart
;
702 DPRINT("Reimagined %x\n", Reimagined
.RunStartVbn
.LowPart
);
705 DPRINT("Found %x\n", Found
);
706 if (!Found
) return MCB_BUMP_NO_MORE
;
709 ("Moving %x-%x to %x because %x-%x overlaps\n",
710 Found
->RunStartVbn
.LowPart
,
711 Found
->RunStartVbn
.LowPart
+ Found
->SectorCount
.QuadPart
,
712 Reimagined
.RunStartVbn
.LowPart
+ Reimagined
.SectorCount
.LowPart
,
713 Reimagined
.RunStartVbn
.LowPart
,
714 Reimagined
.RunStartVbn
.LowPart
+ Reimagined
.SectorCount
.LowPart
);
716 Found
->RunStartVbn
.QuadPart
= Reimagined
.RunStartVbn
.QuadPart
+ Reimagined
.SectorCount
.QuadPart
;
717 Found
->StartingLbn
.QuadPart
= Reimagined
.StartingLbn
.QuadPart
+ Reimagined
.SectorCount
.QuadPart
;
720 return MCB_BUMP_AGAIN
;
728 FsRtlSplitBaseMcb(IN PBASE_MCB OpaqueMcb
,
732 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
734 LARGE_MCB_MAPPING_ENTRY Node
;
735 PLARGE_MCB_MAPPING_ENTRY Existing
= NULL
;
737 Node
.RunStartVbn
.QuadPart
= Vbn
;
738 Node
.SectorCount
.QuadPart
= 0;
740 Existing
= RtlLookupElementGenericTable(&Mcb
->Mapping
->Table
, &Node
);
744 // We're in the middle of a run
745 LARGE_MCB_MAPPING_ENTRY UpperPart
;
746 LARGE_MCB_MAPPING_ENTRY LowerPart
;
747 PLARGE_MCB_MAPPING_ENTRY InsertedUpper
;
749 UpperPart
.RunStartVbn
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Amount
;
750 UpperPart
.SectorCount
.QuadPart
= Existing
->RunStartVbn
.QuadPart
+
751 (Existing
->SectorCount
.QuadPart
- Node
.RunStartVbn
.QuadPart
);
752 UpperPart
.StartingLbn
.QuadPart
= Existing
->StartingLbn
.QuadPart
+
753 (Node
.RunStartVbn
.QuadPart
- Existing
->RunStartVbn
.QuadPart
);
754 LowerPart
.RunStartVbn
.QuadPart
= Existing
->RunStartVbn
.QuadPart
;
755 LowerPart
.SectorCount
.QuadPart
= Node
.RunStartVbn
.QuadPart
- Existing
->RunStartVbn
.QuadPart
;
756 LowerPart
.StartingLbn
.QuadPart
= Existing
->StartingLbn
.QuadPart
;
760 DPRINT("Loop: %x\n", Node
.RunStartVbn
.LowPart
);
761 while ((Result
= McbBump(Mcb
, &Node
)) == MCB_BUMP_AGAIN
)
763 DPRINT("Node: %x\n", Node
.RunStartVbn
.LowPart
);
767 if (Result
== MCB_BUMP_NO_MORE
)
770 RemoveHeadList(&Existing
->Sequence
);
771 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Existing
);
774 // Adjust the element we found.
775 Existing
->SectorCount
= LowerPart
.SectorCount
;
777 InsertedUpper
= RtlInsertElementGenericTable(&Mcb
->Mapping
->Table
, &UpperPart
, sizeof(UpperPart
), NULL
);
780 // Just make it like it was
781 Existing
->SectorCount
= Node
.SectorCount
;
784 InsertHeadList(&Mcb
->Mapping
->SequenceList
, &InsertedUpper
->Sequence
);
789 Node
.RunStartVbn
.QuadPart
= Vbn
;
790 Node
.SectorCount
.QuadPart
= Amount
;
791 while ((Result
= McbBump(Mcb
, &Node
)) == MCB_BUMP_AGAIN
);
792 return Result
== MCB_BUMP_NO_MORE
;
806 FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb
,
812 DPRINT("FsRtlSplitLargeMcb %x, Vbn %x, Amount %x\n", Mcb
, (ULONG
)Vbn
, (ULONG
)Amount
);
814 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
815 Result
= FsRtlSplitBaseMcb(&(Mcb
->BaseMcb
),
818 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
820 DPRINT("Done %d\n", Result
);
830 FsRtlTruncateBaseMcb(IN PBASE_MCB OpaqueMcb
,
833 PBASE_MCB_INTERNAL Mcb
= (PBASE_MCB_INTERNAL
)OpaqueMcb
;
836 FsRtlResetBaseMcb(OpaqueMcb
);
840 LARGE_MCB_MAPPING_ENTRY Truncate
;
841 PLARGE_MCB_MAPPING_ENTRY Found
;
842 Truncate
.RunStartVbn
.QuadPart
= Vbn
;
843 Truncate
.SectorCount
.QuadPart
= (1ull<<62) - Truncate
.RunStartVbn
.QuadPart
;
844 while ((Found
= RtlLookupElementGenericTable(&Mcb
->Mapping
->Table
, &Truncate
)))
846 RemoveEntryList(&Found
->Sequence
);
847 RtlDeleteElementGenericTable(&Mcb
->Mapping
->Table
, Found
);
858 FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb
,
861 DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb
, (ULONG
)Vbn
);
862 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
863 FsRtlTruncateBaseMcb(&(Mcb
->BaseMcb
), Vbn
);
864 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
873 FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb
)
875 FsRtlResetBaseMcb(Mcb
);
877 if ((Mcb
->PoolType
== PagedPool
) && (Mcb
->MaximumPairCount
== MAXIMUM_PAIR_COUNT
))
879 ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList
,
884 ExFreePoolWithTag(Mcb
->Mapping
, 'FSBC');
893 FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb
)
895 if (Mcb
->GuardedMutex
)
897 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList
,
899 FsRtlUninitializeBaseMcb(&(Mcb
->BaseMcb
));