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 #define GET_LIST_HEAD(x) ((PLIST_ENTRY)(&((PRTL_GENERIC_TABLE)x)[1]))
21 PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList
;
22 NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList
;
24 typedef struct _LARGE_MCB_MAPPING_ENTRY
26 LARGE_INTEGER RunStartVbn
;
27 LARGE_INTEGER SectorCount
;
28 LARGE_INTEGER StartingLbn
;
30 } LARGE_MCB_MAPPING_ENTRY
, *PLARGE_MCB_MAPPING_ENTRY
;
32 static VOID
McbPrintTree(PBASE_MCB Mcb
)
34 PLARGE_MCB_MAPPING_ENTRY Entry
;
35 for (Entry
= (PLARGE_MCB_MAPPING_ENTRY
)
36 RtlEnumerateGenericTable(Mcb
->Mapping
, TRUE
);
38 Entry
= (PLARGE_MCB_MAPPING_ENTRY
)
39 RtlEnumerateGenericTable(Mcb
->Mapping
, FALSE
))
42 ("Vbn %x Lbn %x Count %x\n",
43 Entry
->RunStartVbn
.LowPart
,
44 Entry
->StartingLbn
.LowPart
,
45 Entry
->SectorCount
.LowPart
);
49 static PVOID NTAPI
McbMappingAllocate(PRTL_GENERIC_TABLE Table
, CLONG Bytes
)
52 PBASE_MCB Mcb
= (PBASE_MCB
)Table
->TableContext
;
53 Result
= ExAllocatePoolWithTag(Mcb
->PoolType
, Bytes
, 'LMCB');
54 DPRINT("McbMappingAllocate(%d) => %p\n", Bytes
, Result
);
58 static VOID NTAPI
McbMappingFree(PRTL_GENERIC_TABLE Table
, PVOID Buffer
)
60 DPRINT("McbMappingFree(%p)\n", Buffer
);
61 ExFreePoolWithTag(Buffer
, 'LMCB');
64 static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingCompare
65 (PRTL_GENERIC_TABLE Table
, PVOID PtrA
, PVOID PtrB
)
67 PLARGE_MCB_MAPPING_ENTRY A
= PtrA
, B
= PtrB
;
68 RTL_GENERIC_COMPARE_RESULTS Result
;
69 DPRINT("Starting to compare element %x to element %x\n", PtrA
, PtrB
);
71 (A
->RunStartVbn
.QuadPart
+ A
->SectorCount
.QuadPart
<=
72 B
->RunStartVbn
.QuadPart
) ? GenericLessThan
:
73 (A
->RunStartVbn
.QuadPart
>=
74 B
->RunStartVbn
.QuadPart
+ B
->SectorCount
.QuadPart
) ?
75 GenericGreaterThan
: GenericEqual
;
76 DPRINT("Compare(%x:%x): %x:%x to %x:%x => %d\n",
78 A
->RunStartVbn
.LowPart
, A
->SectorCount
.LowPart
,
79 B
->RunStartVbn
.LowPart
, B
->SectorCount
.LowPart
,
84 /* PUBLIC FUNCTIONS **********************************************************/
91 FsRtlAddBaseMcbEntry(IN PBASE_MCB Mcb
,
94 IN LONGLONG SectorCount
)
96 LARGE_MCB_MAPPING_ENTRY Node
;
97 PLARGE_MCB_MAPPING_ENTRY Existing
= NULL
;
98 BOOLEAN NewElement
= FALSE
;
102 Node
.RunStartVbn
.QuadPart
= Vbn
;
103 Node
.StartingLbn
.QuadPart
= Lbn
;
104 Node
.SectorCount
.QuadPart
= SectorCount
;
106 DPRINT("RunStartVbn %x\n", Node
.RunStartVbn
.LowPart
);
107 DPRINT("StartingLbn %x\n", Node
.StartingLbn
.LowPart
);
108 DPRINT("SectorCount %x\n", Node
.SectorCount
.LowPart
);
112 DPRINT("Inserting %x:%x\n", Node
.RunStartVbn
.LowPart
, Node
.SectorCount
.LowPart
);
113 Existing
= RtlInsertElementGenericTable
114 (Mcb
->Mapping
, &Node
, sizeof(Node
), &NewElement
);
115 DPRINT("Existing %x\n", Existing
);
116 if (!Existing
) break;
118 DPRINT("NewElement %d\n", NewElement
);
121 // We merge the existing runs
122 LARGE_INTEGER StartVbn
, FinalVbn
;
123 DPRINT("Existing: %x:%x\n",
124 Existing
->RunStartVbn
.LowPart
, Node
.SectorCount
.LowPart
);
125 if (Existing
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
)
127 StartVbn
= Existing
->RunStartVbn
;
128 Node
.StartingLbn
= Existing
->StartingLbn
;
132 StartVbn
= Node
.RunStartVbn
;
134 DPRINT("StartVbn %x\n", StartVbn
.LowPart
);
135 if (Existing
->RunStartVbn
.QuadPart
+ Existing
->SectorCount
.QuadPart
>
136 Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
)
139 Existing
->RunStartVbn
.QuadPart
+ Existing
->SectorCount
.QuadPart
;
144 Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
;
146 DPRINT("FinalVbn %x\n", FinalVbn
.LowPart
);
147 Node
.RunStartVbn
.QuadPart
= StartVbn
.QuadPart
;
148 Node
.SectorCount
.QuadPart
= FinalVbn
.QuadPart
- StartVbn
.QuadPart
;
149 RemoveHeadList(&Existing
->Sequence
);
150 RtlDeleteElementGenericTable(Mcb
->Mapping
, Existing
);
155 DPRINT("Mapping added %x\n", Existing
);
156 Mcb
->MaximumPairCount
++;
158 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Existing
->Sequence
);
162 DPRINT("!!Existing %d\n", !!Existing
);
172 FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb
,
175 IN LONGLONG SectorCount
)
180 ("Mcb %x Vbn %x Lbn %x SectorCount %x\n",
181 Mcb
, (ULONG
)Vbn
, (ULONG
)Lbn
, (ULONG
)SectorCount
);
183 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
184 Result
= FsRtlAddBaseMcbEntry(&(Mcb
->BaseMcb
),
188 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
190 DPRINT("Done %d\n", Result
);
200 FsRtlGetNextBaseMcbEntry(IN PBASE_MCB Mcb
,
204 OUT PLONGLONG SectorCount
)
207 BOOLEAN Result
= FALSE
;
208 PLARGE_MCB_MAPPING_ENTRY Entry
;
209 for (Entry
= (PLARGE_MCB_MAPPING_ENTRY
)
210 RtlEnumerateGenericTable(Mcb
->Mapping
, TRUE
);
211 Entry
&& i
< RunIndex
;
212 Entry
= (PLARGE_MCB_MAPPING_ENTRY
)
213 RtlEnumerateGenericTable(Mcb
->Mapping
, FALSE
), i
++);
218 *Vbn
= Entry
->RunStartVbn
.QuadPart
;
220 *Lbn
= Entry
->StartingLbn
.QuadPart
;
222 *SectorCount
= Entry
->SectorCount
.QuadPart
;
233 FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb
,
237 OUT PLONGLONG SectorCount
)
241 DPRINT("FsRtlGetNextLargeMcbEntry Mcb %x RunIndex %x\n", Mcb
, RunIndex
);
243 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
244 Result
= FsRtlGetNextBaseMcbEntry(&(Mcb
->BaseMcb
),
249 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
251 DPRINT("Done %d\n", Result
);
261 FsRtlInitializeBaseMcb(IN PBASE_MCB Mcb
,
262 IN POOL_TYPE PoolType
)
266 if (PoolType
== PagedPool
)
268 Mcb
->Mapping
= ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList
);
269 DPRINT("Get from lookaside list\n");
273 Mcb
->Mapping
= ExAllocatePoolWithTag(PoolType
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
274 sizeof(RTL_GENERIC_TABLE
) + sizeof(LIST_ENTRY
),
276 DPRINT("Allocate\n");
279 DPRINT("Mcb->Mapping %x\n", Mcb
->Mapping
);
280 Mcb
->PoolType
= PoolType
;
281 Mcb
->MaximumPairCount
= MAXIMUM_PAIR_COUNT
;
282 RtlInitializeGenericTable
288 InitializeListHead(GET_LIST_HEAD(Mcb
->Mapping
));
296 FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb
,
297 IN POOL_TYPE PoolType
)
299 Mcb
->GuardedMutex
= ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList
);
301 KeInitializeGuardedMutex(Mcb
->GuardedMutex
);
305 FsRtlInitializeBaseMcb(&(Mcb
->BaseMcb
), PoolType
);
307 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
309 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList
,
311 Mcb
->GuardedMutex
= NULL
;
321 FsRtlInitializeLargeMcbs(VOID
)
323 /* Initialize the list for the MCB */
324 ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList
,
327 POOL_RAISE_IF_ALLOCATION_FAILURE
,
328 sizeof(RTL_GENERIC_TABLE
) + sizeof(LIST_ENTRY
),
330 0); /* FIXME: Should be 4 */
332 /* Initialize the list for the guarded mutex */
333 ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList
,
336 POOL_RAISE_IF_ALLOCATION_FAILURE
,
337 sizeof(KGUARDED_MUTEX
),
339 0); /* FIXME: Should be 32 */
347 FsRtlLookupBaseMcbEntry(IN PBASE_MCB Mcb
,
349 OUT PLONGLONG Lbn OPTIONAL
,
350 OUT PLONGLONG SectorCountFromLbn OPTIONAL
,
351 OUT PLONGLONG StartingLbn OPTIONAL
,
352 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL
,
353 OUT PULONG Index OPTIONAL
)
355 BOOLEAN Result
= FALSE
;
356 LARGE_MCB_MAPPING_ENTRY ToLookup
;
357 PLARGE_MCB_MAPPING_ENTRY Entry
;
359 ToLookup
.RunStartVbn
.QuadPart
= Vbn
;
360 ToLookup
.SectorCount
.QuadPart
= 1;
362 Entry
= RtlLookupElementGenericTable(Mcb
->Mapping
, &ToLookup
);
365 // Find out if we have a following entry. The spec says we should return
366 // found with Lbn == -1 when we're beneath the largest map.
367 ToLookup
.SectorCount
.QuadPart
= (1ull<<62) - ToLookup
.RunStartVbn
.QuadPart
;
368 Entry
= RtlLookupElementGenericTable(Mcb
->Mapping
, &ToLookup
);
372 if (Lbn
) *Lbn
= ~0ull;
381 LARGE_INTEGER Offset
;
382 Offset
.QuadPart
= Vbn
- Entry
->RunStartVbn
.QuadPart
;
384 if (Lbn
) *Lbn
= Entry
->StartingLbn
.QuadPart
+ Offset
.QuadPart
;
385 if (SectorCountFromLbn
) *SectorCountFromLbn
= Entry
->SectorCount
.QuadPart
- Offset
.QuadPart
;
386 if (StartingLbn
) *StartingLbn
= Entry
->StartingLbn
.QuadPart
;
387 if (SectorCountFromStartingLbn
) *SectorCountFromStartingLbn
= Entry
->SectorCount
.QuadPart
;
398 FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb
,
400 OUT PLONGLONG Lbn OPTIONAL
,
401 OUT PLONGLONG SectorCountFromLbn OPTIONAL
,
402 OUT PLONGLONG StartingLbn OPTIONAL
,
403 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL
,
404 OUT PULONG Index OPTIONAL
)
408 DPRINT("FsRtlLookupLargeMcbEntry Mcb %x Vbn %x\n", Mcb
, (ULONG
)Vbn
);
410 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
411 Result
= FsRtlLookupBaseMcbEntry(&(Mcb
->BaseMcb
),
416 SectorCountFromStartingLbn
,
418 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
420 DPRINT("Done %d (%x)\n", Result
, Lbn
? (ULONG
)*Lbn
: 0);
430 FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb
,
431 IN OUT PLONGLONG LargeVbn
,
432 IN OUT PLONGLONG LargeLbn
,
436 BOOLEAN Result
= FALSE
;
437 PLIST_ENTRY ListEntry
;
438 PLARGE_MCB_MAPPING_ENTRY Entry
;
439 PLARGE_MCB_MAPPING_ENTRY CountEntry
;
441 ListEntry
= GET_LIST_HEAD(OpaqueMcb
->Mapping
);
442 if (!IsListEmpty(ListEntry
))
444 Entry
= CONTAINING_RECORD(ListEntry
->Flink
, LARGE_MCB_MAPPING_ENTRY
, Sequence
);
446 *LargeVbn
= Entry
->RunStartVbn
.QuadPart
;
447 *LargeLbn
= Entry
->StartingLbn
.QuadPart
;
449 for (i
= 0, CountEntry
= RtlEnumerateGenericTable(OpaqueMcb
->Mapping
, TRUE
);
451 CountEntry
= RtlEnumerateGenericTable(OpaqueMcb
->Mapping
, FALSE
));
464 FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb
,
465 OUT PLONGLONG LargeVbn
,
466 OUT PLONGLONG LargeLbn
,
471 DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex %x\n", OpaqueMcb
);
473 KeAcquireGuardedMutex(OpaqueMcb
->GuardedMutex
);
474 Result
= FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb
->BaseMcb
),
478 KeReleaseGuardedMutex(OpaqueMcb
->GuardedMutex
);
480 DPRINT("Done %d\n", Result
);
490 FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB Mcb
,
494 BOOLEAN Result
= FALSE
;
495 PLIST_ENTRY ListEntry
;
496 PLARGE_MCB_MAPPING_ENTRY Entry
;
498 ListEntry
= GET_LIST_HEAD(Mcb
->Mapping
);
499 if (!IsListEmpty(ListEntry
))
501 Entry
= CONTAINING_RECORD(ListEntry
->Flink
, LARGE_MCB_MAPPING_ENTRY
, Sequence
);
503 *Vbn
= Entry
->RunStartVbn
.QuadPart
;
504 *Lbn
= Entry
->StartingLbn
.QuadPart
;
515 FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb
,
521 DPRINT("FsRtlLookupLastLargeMcbEntry Mcb %x\n", Mcb
);
523 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
524 Result
= FsRtlLookupLastBaseMcbEntry(&(Mcb
->BaseMcb
),
527 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
529 DPRINT("Done %d\n", Result
);
539 FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB Mcb
)
541 /* Return the count */
542 return Mcb
->PairCount
;
550 FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb
)
554 DPRINT("FsRtlNumberOfRunsInLargeMcb Mcb %x\n", Mcb
);
556 /* Read the number of runs while holding the MCB lock */
557 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
558 NumberOfRuns
= Mcb
->BaseMcb
.PairCount
;
559 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
561 DPRINT("Done %d\n", NumberOfRuns
);
563 /* Return the count */
572 FsRtlRemoveBaseMcbEntry(IN PBASE_MCB Mcb
,
574 IN LONGLONG SectorCount
)
576 LARGE_MCB_MAPPING_ENTRY Node
;
577 PLARGE_MCB_MAPPING_ENTRY Element
;
579 Node
.RunStartVbn
.QuadPart
= Vbn
;
580 Node
.SectorCount
.QuadPart
= SectorCount
;
582 while ((Element
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Node
)))
585 if (Element
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
&&
586 Element
->SectorCount
.QuadPart
> Node
.SectorCount
.QuadPart
)
588 LARGE_MCB_MAPPING_ENTRY Upper
, Reinsert
;
589 PLARGE_MCB_MAPPING_ENTRY Reinserted
, Inserted
;
590 LARGE_INTEGER StartHole
= Node
.RunStartVbn
;
591 LARGE_INTEGER EndHole
;
592 EndHole
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
;
593 Upper
.RunStartVbn
.QuadPart
= EndHole
.QuadPart
;
594 Upper
.StartingLbn
.QuadPart
=
595 Element
->StartingLbn
.QuadPart
+
597 Element
->RunStartVbn
.QuadPart
;
598 Upper
.SectorCount
.QuadPart
=
599 Element
->SectorCount
.QuadPart
-
600 (EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
);
602 Reinsert
.SectorCount
.QuadPart
=
603 Element
->RunStartVbn
.QuadPart
- StartHole
.QuadPart
;
604 RemoveEntryList(&Element
->Sequence
);
605 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
608 Reinserted
= RtlInsertElementGenericTable
609 (Mcb
->Mapping
, &Reinsert
, sizeof(Reinsert
), NULL
);
610 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Reinserted
->Sequence
);
613 Inserted
= RtlInsertElementGenericTable
614 (Mcb
->Mapping
, &Upper
, sizeof(Upper
), NULL
);
615 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Inserted
->Sequence
);
618 else if (Element
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
)
620 LARGE_MCB_MAPPING_ENTRY NewElement
;
621 PLARGE_MCB_MAPPING_ENTRY Reinserted
;
622 LARGE_INTEGER StartHole
= Node
.RunStartVbn
;
623 NewElement
.RunStartVbn
= Element
->RunStartVbn
;
624 NewElement
.StartingLbn
= Element
->StartingLbn
;
625 NewElement
.SectorCount
.QuadPart
= StartHole
.QuadPart
- Element
->StartingLbn
.QuadPart
;
627 RemoveEntryList(&Element
->Sequence
);
628 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
631 Reinserted
= RtlInsertElementGenericTable
632 (Mcb
->Mapping
, &NewElement
, sizeof(NewElement
), NULL
);
633 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Reinserted
->Sequence
);
638 LARGE_MCB_MAPPING_ENTRY NewElement
;
639 PLARGE_MCB_MAPPING_ENTRY Reinserted
;
640 LARGE_INTEGER EndHole
= Element
->RunStartVbn
;
641 LARGE_INTEGER EndRun
;
642 EndRun
.QuadPart
= Element
->RunStartVbn
.QuadPart
+ Element
->SectorCount
.QuadPart
;
643 NewElement
.RunStartVbn
= EndHole
;
644 NewElement
.StartingLbn
.QuadPart
= Element
->StartingLbn
.QuadPart
+
645 (EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
);
646 NewElement
.SectorCount
.QuadPart
= EndRun
.QuadPart
- EndHole
.QuadPart
;
648 RemoveEntryList(&Element
->Sequence
);
649 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
652 Reinserted
= RtlInsertElementGenericTable
653 (Mcb
->Mapping
, &NewElement
, sizeof(NewElement
), NULL
);
654 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Reinserted
->Sequence
);
665 FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb
,
667 IN LONGLONG SectorCount
)
669 DPRINT("FsRtlRemoveLargeMcbEntry Mcb %x, Vbn %x, SectorCount %x\n", Mcb
, (ULONG
)Vbn
, (ULONG
)SectorCount
);
671 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
672 FsRtlRemoveBaseMcbEntry(&(Mcb
->BaseMcb
),
675 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
685 FsRtlResetBaseMcb(IN PBASE_MCB Mcb
)
687 PLARGE_MCB_MAPPING_ENTRY Element
;
689 DPRINT("Reset MCB %x\n", Mcb
);
690 while (RtlNumberGenericTableElements(Mcb
->Mapping
) &&
691 (Element
= (PLARGE_MCB_MAPPING_ENTRY
)RtlGetElementGenericTable(Mcb
->Mapping
, 0)))
693 DPRINT("Deleting %x\n", Element
);
694 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
698 Mcb
->MaximumPairCount
= 0;
707 FsRtlResetLargeMcb(IN PLARGE_MCB Mcb
,
708 IN BOOLEAN SelfSynchronized
)
710 if (!SelfSynchronized
)
712 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
715 FsRtlResetBaseMcb(&Mcb
->BaseMcb
);
718 if (!SelfSynchronized
)
720 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
724 #define MCB_BUMP_NO_MORE 0
725 #define MCB_BUMP_AGAIN 1
727 static ULONG NTAPI
McbBump(PBASE_MCB Mcb
, PLARGE_MCB_MAPPING_ENTRY FixedPart
)
729 LARGE_MCB_MAPPING_ENTRY Reimagined
;
730 PLARGE_MCB_MAPPING_ENTRY Found
= NULL
;
732 DPRINT("McbBump %x (%x:%x)\n", Mcb
, FixedPart
->RunStartVbn
.LowPart
, FixedPart
->SectorCount
.LowPart
);
734 Reimagined
= *FixedPart
;
735 while ((Found
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Reimagined
)))
738 Reimagined
.RunStartVbn
.QuadPart
=
739 FixedPart
->RunStartVbn
.QuadPart
+ FixedPart
->SectorCount
.QuadPart
;
740 DPRINT("Reimagined %x\n", Reimagined
.RunStartVbn
.LowPart
);
743 DPRINT("Found %x\n", Found
);
744 if (!Found
) return MCB_BUMP_NO_MORE
;
746 ("Moving %x-%x to %x because %x-%x overlaps\n",
747 Found
->RunStartVbn
.LowPart
,
748 Found
->RunStartVbn
.LowPart
+ Found
->SectorCount
.QuadPart
,
749 Reimagined
.RunStartVbn
.LowPart
+ Reimagined
.SectorCount
.LowPart
,
750 Reimagined
.RunStartVbn
.LowPart
,
751 Reimagined
.RunStartVbn
.LowPart
+ Reimagined
.SectorCount
.LowPart
);
752 Found
->RunStartVbn
.QuadPart
= Reimagined
.RunStartVbn
.QuadPart
+ Reimagined
.SectorCount
.QuadPart
;
753 Found
->StartingLbn
.QuadPart
= Reimagined
.StartingLbn
.QuadPart
+ Reimagined
.SectorCount
.QuadPart
;
756 return MCB_BUMP_AGAIN
;
764 FsRtlSplitBaseMcb(IN PBASE_MCB Mcb
,
769 LARGE_MCB_MAPPING_ENTRY Node
;
770 PLARGE_MCB_MAPPING_ENTRY Existing
= NULL
;
772 Node
.RunStartVbn
.QuadPart
= Vbn
;
773 Node
.SectorCount
.QuadPart
= 0;
775 Existing
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Node
);
779 // We're in the middle of a run
780 LARGE_MCB_MAPPING_ENTRY UpperPart
;
781 LARGE_MCB_MAPPING_ENTRY LowerPart
;
782 PLARGE_MCB_MAPPING_ENTRY InsertedUpper
;
784 UpperPart
.RunStartVbn
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Amount
;
785 UpperPart
.SectorCount
.QuadPart
= Existing
->RunStartVbn
.QuadPart
+
786 (Existing
->SectorCount
.QuadPart
- Node
.RunStartVbn
.QuadPart
);
787 UpperPart
.StartingLbn
.QuadPart
= Existing
->StartingLbn
.QuadPart
+
788 (Node
.RunStartVbn
.QuadPart
- Existing
->RunStartVbn
.QuadPart
);
789 LowerPart
.RunStartVbn
.QuadPart
= Existing
->RunStartVbn
.QuadPart
;
790 LowerPart
.SectorCount
.QuadPart
= Node
.RunStartVbn
.QuadPart
- Existing
->RunStartVbn
.QuadPart
;
791 LowerPart
.StartingLbn
.QuadPart
= Existing
->StartingLbn
.QuadPart
;
795 DPRINT("Loop: %x\n", Node
.RunStartVbn
.LowPart
);
796 while ((Result
= McbBump(Mcb
, &Node
)) == MCB_BUMP_AGAIN
)
798 DPRINT("Node: %x\n", Node
.RunStartVbn
.LowPart
);
802 if (Result
== MCB_BUMP_NO_MORE
)
805 RemoveHeadList(&Existing
->Sequence
);
806 RtlDeleteElementGenericTable(Mcb
->Mapping
, Existing
);
809 // Adjust the element we found.
810 Existing
->SectorCount
= LowerPart
.SectorCount
;
812 InsertedUpper
= RtlInsertElementGenericTable
813 (Mcb
->Mapping
, &UpperPart
, sizeof(UpperPart
), NULL
);
816 // Just make it like it was
817 Existing
->SectorCount
= Node
.SectorCount
;
820 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &InsertedUpper
->Sequence
);
825 Node
.RunStartVbn
.QuadPart
= Vbn
;
826 Node
.SectorCount
.QuadPart
= Amount
;
827 while ((Result
= McbBump(Mcb
, &Node
)) == MCB_BUMP_AGAIN
);
828 return Result
== MCB_BUMP_NO_MORE
;
842 FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb
,
848 DPRINT("FsRtlSplitLargeMcb %x, Vbn %x, Amount %x\n", Mcb
, (ULONG
)Vbn
, (ULONG
)Amount
);
850 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
851 Result
= FsRtlSplitBaseMcb(&(Mcb
->BaseMcb
),
854 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
856 DPRINT("Done %d\n", Result
);
866 FsRtlTruncateBaseMcb(IN PBASE_MCB Mcb
,
869 DPRINT("FsRtlTruncateBaseMcb(%x,%x)\n", Mcb
, (ULONG
)Vbn
);
872 DPRINT("Resetting\n");
873 FsRtlResetBaseMcb(Mcb
);
877 LARGE_MCB_MAPPING_ENTRY Truncate
;
878 PLARGE_MCB_MAPPING_ENTRY Found
;
879 Truncate
.RunStartVbn
.QuadPart
= Vbn
;
880 Truncate
.SectorCount
.QuadPart
= (1ull<<62) - Truncate
.RunStartVbn
.QuadPart
;
881 while ((Found
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Truncate
)))
883 DPRINT("Deleting %x\n", Found
);
884 RemoveEntryList(&Found
->Sequence
);
885 RtlDeleteElementGenericTable(Mcb
->Mapping
, Found
);
897 FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb
,
900 DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb
, (ULONG
)Vbn
);
901 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
902 FsRtlTruncateBaseMcb(&(Mcb
->BaseMcb
),
904 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
913 FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb
)
915 DPRINT("FsRtlUninitializeBaseMcb(%x)\n", Mcb
);
916 FsRtlResetBaseMcb(Mcb
);
918 DPRINT("Mcb->Mapping %x\n", Mcb
->Mapping
);
919 if (Mcb
->PoolType
== PagedPool
)
921 DPRINT("Deallocate to lookaside list\n");
922 ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList
,
927 DPRINT("Deallocate\n");
928 ExFreePoolWithTag(Mcb
->Mapping
, 'FSBC');
939 FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb
)
941 if (Mcb
->GuardedMutex
)
943 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList
,
945 Mcb
->GuardedMutex
= NULL
;
946 FsRtlUninitializeBaseMcb(&(Mcb
->BaseMcb
));
957 FsRtlAddMcbEntry(IN PMCB Mcb
,
960 IN ULONG SectorCount
)
962 /* Call the newer function */
963 return FsRtlAddLargeMcbEntry(&Mcb
->
964 DummyFieldThatSizesThisStructureCorrectly
,
967 (LONGLONG
)SectorCount
);
975 FsRtlGetNextMcbEntry(IN PMCB Mcb
,
979 OUT PULONG SectorCount
)
981 BOOLEAN Return
= FALSE
;
984 LONGLONG llSectorCount
;
986 /* Call the Large version */
987 Return
= FsRtlGetNextLargeMcbEntry(
988 &Mcb
->DummyFieldThatSizesThisStructureCorrectly
,
994 /* Return the lower 32 bits */
997 *SectorCount
= (ULONG
)llSectorCount
;
999 /* And return the original value */
1008 FsRtlInitializeMcb(IN PMCB Mcb
,
1009 IN POOL_TYPE PoolType
)
1011 /* Call the newer function */
1012 FsRtlInitializeLargeMcb(&Mcb
->DummyFieldThatSizesThisStructureCorrectly
,
1021 FsRtlLookupLastMcbEntry(IN PMCB Mcb
,
1025 BOOLEAN Return
= FALSE
;
1029 /* Call the Large version */
1030 Return
= FsRtlLookupLastLargeMcbEntry(
1031 &Mcb
->DummyFieldThatSizesThisStructureCorrectly
,
1035 /* Return the lower 32-bits */
1036 *Vbn
= (ULONG
)llVbn
;
1037 *Lbn
= (ULONG
)llLbn
;
1039 /* And return the original value */
1048 FsRtlLookupMcbEntry(IN PMCB Mcb
,
1051 OUT PULONG SectorCount OPTIONAL
,
1054 BOOLEAN Return
= FALSE
;
1056 LONGLONG llSectorCount
;
1058 /* Call the Large version */
1059 Return
= FsRtlLookupLargeMcbEntry(&Mcb
->
1060 DummyFieldThatSizesThisStructureCorrectly
,
1068 /* Return the lower 32-bits */
1069 *Lbn
= (ULONG
)llLbn
;
1070 if (SectorCount
) *SectorCount
= (ULONG
)llSectorCount
;
1072 /* And return the original value */
1081 FsRtlNumberOfRunsInMcb(IN PMCB Mcb
)
1083 /* Call the newer function */
1084 return FsRtlNumberOfRunsInLargeMcb(
1085 &Mcb
->DummyFieldThatSizesThisStructureCorrectly
);
1093 FsRtlRemoveMcbEntry(IN PMCB Mcb
,
1095 IN ULONG SectorCount
)
1097 /* Call the large function */
1098 FsRtlRemoveLargeMcbEntry(&Mcb
->DummyFieldThatSizesThisStructureCorrectly
,
1100 (LONGLONG
)SectorCount
);
1108 FsRtlTruncateMcb(IN PMCB Mcb
,
1111 /* Call the newer function */
1112 FsRtlTruncateLargeMcb(&Mcb
->DummyFieldThatSizesThisStructureCorrectly
,
1121 FsRtlUninitializeMcb(IN PMCB Mcb
)
1123 /* Call the newer function */
1124 FsRtlUninitializeLargeMcb(&Mcb
->DummyFieldThatSizesThisStructureCorrectly
);