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 PVOID NTAPI
McbMappingAllocate(PRTL_GENERIC_TABLE Table
, CLONG Bytes
)
35 PBASE_MCB Mcb
= (PBASE_MCB
)Table
->TableContext
;
36 Result
= ExAllocatePoolWithTag(Mcb
->PoolType
, Bytes
, 'LMCB');
37 DPRINT("McbMappingAllocate(%d) => %p\n", Bytes
, Result
);
41 static VOID NTAPI
McbMappingFree(PRTL_GENERIC_TABLE Table
, PVOID Buffer
)
43 DPRINT("McbMappingFree(%p)\n", Buffer
);
44 ExFreePoolWithTag(Buffer
, 'LMCB');
47 static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingCompare
48 (RTL_GENERIC_TABLE Table
, PVOID PtrA
, PVOID PtrB
)
50 PLARGE_MCB_MAPPING_ENTRY A
= PtrA
, B
= PtrB
;
52 (A
->RunStartVbn
.QuadPart
+ A
->SectorCount
.QuadPart
<
53 B
->RunStartVbn
.QuadPart
) ? GenericLessThan
:
54 (A
->RunStartVbn
.QuadPart
>
55 B
->RunStartVbn
.QuadPart
+ B
->SectorCount
.QuadPart
) ?
56 GenericGreaterThan
: GenericEqual
;
59 /* PUBLIC FUNCTIONS **********************************************************/
66 FsRtlAddBaseMcbEntry(IN PBASE_MCB Mcb
,
69 IN LONGLONG SectorCount
)
71 LARGE_MCB_MAPPING_ENTRY Node
;
72 PLARGE_MCB_MAPPING_ENTRY Existing
= NULL
;
73 BOOLEAN NewElement
= FALSE
;
75 Node
.RunStartVbn
.QuadPart
= Vbn
;
76 Node
.StartingLbn
.QuadPart
= Lbn
;
77 Node
.SectorCount
.QuadPart
= SectorCount
;
81 DPRINT("Inserting %x:%x\n", Node
.RunStartVbn
.LowPart
, Node
.SectorCount
.LowPart
);
82 Existing
= RtlInsertElementGenericTable
83 (Mcb
->Mapping
, &Node
, sizeof(Node
), &NewElement
);
84 DPRINT("Existing %x\n", Existing
);
87 DPRINT("NewElement %d\n", NewElement
);
90 // We merge the existing runs
91 LARGE_INTEGER StartVbn
, FinalVbn
;
92 DPRINT("Existing: %x:%x\n",
93 Existing
->RunStartVbn
.LowPart
, Node
.SectorCount
.LowPart
);
94 if (Existing
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
)
96 StartVbn
= Existing
->RunStartVbn
;
97 Node
.StartingLbn
= Existing
->StartingLbn
;
101 StartVbn
= Node
.RunStartVbn
;
103 DPRINT("StartVbn %x\n", StartVbn
.LowPart
);
104 if (Existing
->RunStartVbn
.QuadPart
+ Existing
->SectorCount
.QuadPart
>
105 Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
)
108 Existing
->RunStartVbn
.QuadPart
+ Existing
->SectorCount
.QuadPart
;
113 Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
;
115 DPRINT("FinalVbn %x\n", FinalVbn
.LowPart
);
116 Node
.RunStartVbn
.QuadPart
= StartVbn
.QuadPart
;
117 Node
.SectorCount
.QuadPart
= FinalVbn
.QuadPart
- StartVbn
.QuadPart
;
118 RemoveHeadList(&Existing
->Sequence
);
119 RtlDeleteElementGenericTable(Mcb
->Mapping
, Existing
);
124 DPRINT("Mapping added %x\n", Existing
);
125 Mcb
->MaximumPairCount
++;
127 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Existing
->Sequence
);
131 DPRINT("!!Existing %d\n", !!Existing
);
140 FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb
,
143 IN LONGLONG SectorCount
)
147 DPRINT("Mcb %x Vbn %x Lbn %x SectorCount %x\n", Mcb
, Vbn
, Lbn
, SectorCount
);
149 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
150 Result
= FsRtlAddBaseMcbEntry(&(Mcb
->BaseMcb
),
154 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
156 DPRINT("Done %d\n", Result
);
166 FsRtlGetNextBaseMcbEntry(IN PBASE_MCB Mcb
,
170 OUT PLONGLONG SectorCount
)
173 BOOLEAN Result
= FALSE
;
174 PLARGE_MCB_MAPPING_ENTRY Entry
;
175 for (Entry
= (PLARGE_MCB_MAPPING_ENTRY
)
176 RtlEnumerateGenericTable(Mcb
->Mapping
, TRUE
);
177 Entry
&& i
< RunIndex
;
178 Entry
= (PLARGE_MCB_MAPPING_ENTRY
)
179 RtlEnumerateGenericTable(Mcb
->Mapping
, FALSE
), i
++);
184 *Vbn
= Entry
->RunStartVbn
.QuadPart
;
186 *Lbn
= Entry
->StartingLbn
.QuadPart
;
188 *SectorCount
= Entry
->SectorCount
.QuadPart
;
199 FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb
,
203 OUT PLONGLONG SectorCount
)
207 DPRINT("FsRtlGetNextLargeMcbEntry Mcb %x RunIndex %x\n", Mcb
, RunIndex
);
209 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
210 Result
= FsRtlGetNextBaseMcbEntry(&(Mcb
->BaseMcb
),
215 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
217 DPRINT("Done %d\n", Result
);
227 FsRtlInitializeBaseMcb(IN PBASE_MCB Mcb
,
228 IN POOL_TYPE PoolType
)
232 if (PoolType
== PagedPool
)
234 Mcb
->Mapping
= ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList
);
238 Mcb
->Mapping
= ExAllocatePoolWithTag(PoolType
| POOL_RAISE_IF_ALLOCATION_FAILURE
,
239 sizeof(RTL_GENERIC_TABLE
) + sizeof(LIST_ENTRY
),
243 Mcb
->PoolType
= PoolType
;
244 Mcb
->MaximumPairCount
= MAXIMUM_PAIR_COUNT
;
245 RtlInitializeGenericTable
247 (PRTL_GENERIC_COMPARE_ROUTINE
)McbMappingCompare
,
251 InitializeListHead(GET_LIST_HEAD(Mcb
->Mapping
));
259 FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb
,
260 IN POOL_TYPE PoolType
)
262 Mcb
->GuardedMutex
= ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList
);
264 KeInitializeGuardedMutex(Mcb
->GuardedMutex
);
268 FsRtlInitializeBaseMcb(&(Mcb
->BaseMcb
), PoolType
);
270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
272 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList
,
274 Mcb
->GuardedMutex
= NULL
;
284 FsRtlInitializeLargeMcbs(VOID
)
286 /* Initialize the list for the MCB */
287 ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList
,
290 POOL_RAISE_IF_ALLOCATION_FAILURE
,
291 sizeof(RTL_GENERIC_TABLE
) + sizeof(LIST_ENTRY
),
293 0); /* FIXME: Should be 4 */
295 /* Initialize the list for the guarded mutex */
296 ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList
,
299 POOL_RAISE_IF_ALLOCATION_FAILURE
,
300 sizeof(KGUARDED_MUTEX
),
302 0); /* FIXME: Should be 32 */
310 FsRtlLookupBaseMcbEntry(IN PBASE_MCB Mcb
,
312 OUT PLONGLONG Lbn OPTIONAL
,
313 OUT PLONGLONG SectorCountFromLbn OPTIONAL
,
314 OUT PLONGLONG StartingLbn OPTIONAL
,
315 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL
,
316 OUT PULONG Index OPTIONAL
)
318 BOOLEAN Result
= FALSE
;
319 LARGE_MCB_MAPPING_ENTRY ToLookup
;
320 PLARGE_MCB_MAPPING_ENTRY Entry
;
322 ToLookup
.RunStartVbn
.QuadPart
= Vbn
;
323 ToLookup
.SectorCount
.QuadPart
= 1;
325 Entry
= RtlLookupElementGenericTable(Mcb
->Mapping
, &ToLookup
);
328 // Find out if we have a following entry. The spec says we should return
329 // found with Lbn == -1 when we're beneath the largest map.
330 ToLookup
.SectorCount
.QuadPart
= (1ull<<62) - ToLookup
.RunStartVbn
.QuadPart
;
331 Entry
= RtlLookupElementGenericTable(Mcb
->Mapping
, &ToLookup
);
335 if (Lbn
) *Lbn
= ~0ull;
344 LARGE_INTEGER Offset
;
345 Offset
.QuadPart
= Vbn
- Entry
->RunStartVbn
.QuadPart
;
347 if (Lbn
) *Lbn
= Entry
->StartingLbn
.QuadPart
+ Offset
.QuadPart
;
348 if (SectorCountFromLbn
) *SectorCountFromLbn
= Entry
->SectorCount
.QuadPart
- Offset
.QuadPart
;
349 if (StartingLbn
) *StartingLbn
= Entry
->StartingLbn
.QuadPart
;
350 if (SectorCountFromStartingLbn
) *SectorCountFromStartingLbn
= Entry
->SectorCount
.QuadPart
;
361 FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb
,
363 OUT PLONGLONG Lbn OPTIONAL
,
364 OUT PLONGLONG SectorCountFromLbn OPTIONAL
,
365 OUT PLONGLONG StartingLbn OPTIONAL
,
366 OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL
,
367 OUT PULONG Index OPTIONAL
)
371 DPRINT("FsRtlLookupLargeMcbEntry Mcb %x Vbn %x\n", Mcb
, (ULONG
)Vbn
);
373 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
374 Result
= FsRtlLookupBaseMcbEntry(&(Mcb
->BaseMcb
),
379 SectorCountFromStartingLbn
,
381 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
383 DPRINT("Done %d\n", Result
);
393 FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb
,
394 IN OUT PLONGLONG LargeVbn
,
395 IN OUT PLONGLONG LargeLbn
,
399 BOOLEAN Result
= FALSE
;
400 PLIST_ENTRY ListEntry
;
401 PLARGE_MCB_MAPPING_ENTRY Entry
;
402 PLARGE_MCB_MAPPING_ENTRY CountEntry
;
404 ListEntry
= GET_LIST_HEAD(OpaqueMcb
->Mapping
);
405 if (!IsListEmpty(ListEntry
))
407 Entry
= CONTAINING_RECORD(ListEntry
->Flink
, LARGE_MCB_MAPPING_ENTRY
, Sequence
);
409 *LargeVbn
= Entry
->RunStartVbn
.QuadPart
;
410 *LargeLbn
= Entry
->StartingLbn
.QuadPart
;
412 for (i
= 0, CountEntry
= RtlEnumerateGenericTable(OpaqueMcb
->Mapping
, TRUE
);
414 CountEntry
= RtlEnumerateGenericTable(OpaqueMcb
->Mapping
, FALSE
));
427 FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb
,
428 OUT PLONGLONG LargeVbn
,
429 OUT PLONGLONG LargeLbn
,
434 DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex %x\n", OpaqueMcb
);
436 KeAcquireGuardedMutex(OpaqueMcb
->GuardedMutex
);
437 Result
= FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb
->BaseMcb
),
441 KeReleaseGuardedMutex(OpaqueMcb
->GuardedMutex
);
443 DPRINT("Done %d\n", Result
);
453 FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB Mcb
,
457 BOOLEAN Result
= FALSE
;
458 PLIST_ENTRY ListEntry
;
459 PLARGE_MCB_MAPPING_ENTRY Entry
;
461 ListEntry
= GET_LIST_HEAD(Mcb
->Mapping
);
462 if (!IsListEmpty(ListEntry
))
464 Entry
= CONTAINING_RECORD(ListEntry
->Flink
, LARGE_MCB_MAPPING_ENTRY
, Sequence
);
466 *Vbn
= Entry
->RunStartVbn
.QuadPart
;
467 *Lbn
= Entry
->StartingLbn
.QuadPart
;
478 FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb
,
484 DPRINT("FsRtlLookupLastLargeMcbEntry Mcb %x\n", Mcb
);
486 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
487 Result
= FsRtlLookupLastBaseMcbEntry(&(Mcb
->BaseMcb
),
490 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
492 DPRINT("Done %d\n", Result
);
502 FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB Mcb
)
504 /* Return the count */
505 return Mcb
->PairCount
;
513 FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb
)
517 DPRINT("FsRtlNumberOfRunsInLargeMcb Mcb %x\n", Mcb
);
519 /* Read the number of runs while holding the MCB lock */
520 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
521 NumberOfRuns
= Mcb
->BaseMcb
.PairCount
;
522 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
524 DPRINT("Done %d\n", NumberOfRuns
);
526 /* Return the count */
535 FsRtlRemoveBaseMcbEntry(IN PBASE_MCB Mcb
,
537 IN LONGLONG SectorCount
)
539 LARGE_MCB_MAPPING_ENTRY Node
;
540 PLARGE_MCB_MAPPING_ENTRY Element
;
542 Node
.RunStartVbn
.QuadPart
= Vbn
;
543 Node
.SectorCount
.QuadPart
= SectorCount
;
545 while ((Element
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Node
)))
548 if (Element
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
&&
549 Element
->SectorCount
.QuadPart
> Node
.SectorCount
.QuadPart
)
551 LARGE_MCB_MAPPING_ENTRY Upper
, Reinsert
;
552 PLARGE_MCB_MAPPING_ENTRY Reinserted
, Inserted
;
553 LARGE_INTEGER StartHole
= Node
.RunStartVbn
;
554 LARGE_INTEGER EndHole
;
555 EndHole
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Node
.SectorCount
.QuadPart
;
556 Upper
.RunStartVbn
.QuadPart
= EndHole
.QuadPart
;
557 Upper
.StartingLbn
.QuadPart
=
558 Element
->StartingLbn
.QuadPart
+
560 Element
->RunStartVbn
.QuadPart
;
561 Upper
.SectorCount
.QuadPart
=
562 Element
->SectorCount
.QuadPart
-
563 (EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
);
565 Reinsert
.SectorCount
.QuadPart
=
566 Element
->RunStartVbn
.QuadPart
- StartHole
.QuadPart
;
567 RemoveEntryList(&Element
->Sequence
);
568 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
571 Reinserted
= RtlInsertElementGenericTable
572 (Mcb
->Mapping
, &Reinsert
, sizeof(Reinsert
), NULL
);
573 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Reinserted
->Sequence
);
576 Inserted
= RtlInsertElementGenericTable
577 (Mcb
->Mapping
, &Upper
, sizeof(Upper
), NULL
);
578 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Inserted
->Sequence
);
581 else if (Element
->RunStartVbn
.QuadPart
< Node
.RunStartVbn
.QuadPart
)
583 LARGE_MCB_MAPPING_ENTRY NewElement
;
584 PLARGE_MCB_MAPPING_ENTRY Reinserted
;
585 LARGE_INTEGER StartHole
= Node
.RunStartVbn
;
586 NewElement
.RunStartVbn
= Element
->RunStartVbn
;
587 NewElement
.StartingLbn
= Element
->StartingLbn
;
588 NewElement
.SectorCount
.QuadPart
= StartHole
.QuadPart
- Element
->StartingLbn
.QuadPart
;
590 RemoveEntryList(&Element
->Sequence
);
591 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
594 Reinserted
= RtlInsertElementGenericTable
595 (Mcb
->Mapping
, &NewElement
, sizeof(NewElement
), NULL
);
596 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Reinserted
->Sequence
);
601 LARGE_MCB_MAPPING_ENTRY NewElement
;
602 PLARGE_MCB_MAPPING_ENTRY Reinserted
;
603 LARGE_INTEGER EndHole
= Element
->RunStartVbn
;
604 LARGE_INTEGER EndRun
;
605 EndRun
.QuadPart
= Element
->RunStartVbn
.QuadPart
+ Element
->SectorCount
.QuadPart
;
606 NewElement
.RunStartVbn
= EndHole
;
607 NewElement
.StartingLbn
.QuadPart
= Element
->StartingLbn
.QuadPart
+
608 (EndHole
.QuadPart
- Element
->RunStartVbn
.QuadPart
);
609 NewElement
.SectorCount
.QuadPart
= EndRun
.QuadPart
- EndHole
.QuadPart
;
611 RemoveEntryList(&Element
->Sequence
);
612 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
615 Reinserted
= RtlInsertElementGenericTable
616 (Mcb
->Mapping
, &NewElement
, sizeof(NewElement
), NULL
);
617 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &Reinserted
->Sequence
);
630 FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb
,
632 IN LONGLONG SectorCount
)
634 DPRINT("FsRtlRemoveLargeMcbEntry Mcb %x, Vbn %x, SectorCount %x\n", Mcb
, (ULONG
)Vbn
, (ULONG
)SectorCount
);
636 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
637 FsRtlRemoveBaseMcbEntry(&(Mcb
->BaseMcb
),
640 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
650 FsRtlResetBaseMcb(IN PBASE_MCB Mcb
)
652 PLARGE_MCB_MAPPING_ENTRY Element
;
654 while (RtlNumberGenericTableElements(Mcb
->Mapping
) &&
655 (Element
= (PLARGE_MCB_MAPPING_ENTRY
)RtlGetElementGenericTable(Mcb
->Mapping
, 0)))
657 RtlDeleteElementGenericTable(Mcb
->Mapping
, Element
);
661 Mcb
->MaximumPairCount
= 0;
669 FsRtlResetLargeMcb(IN PLARGE_MCB Mcb
,
670 IN BOOLEAN SelfSynchronized
)
672 if (!SelfSynchronized
)
674 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
677 FsRtlResetBaseMcb(&Mcb
->BaseMcb
);
680 if (!SelfSynchronized
)
682 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
686 #define MCB_BUMP_NO_MORE 0
687 #define MCB_BUMP_AGAIN 1
689 static ULONG NTAPI
McbBump(PBASE_MCB 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
, &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
;
708 ("Moving %x-%x to %x because %x-%x overlaps\n",
709 Found
->RunStartVbn
.LowPart
,
710 Found
->RunStartVbn
.LowPart
+ Found
->SectorCount
.QuadPart
,
711 Reimagined
.RunStartVbn
.LowPart
+ Reimagined
.SectorCount
.LowPart
,
712 Reimagined
.RunStartVbn
.LowPart
,
713 Reimagined
.RunStartVbn
.LowPart
+ Reimagined
.SectorCount
.LowPart
);
714 Found
->RunStartVbn
.QuadPart
= Reimagined
.RunStartVbn
.QuadPart
+ Reimagined
.SectorCount
.QuadPart
;
715 Found
->StartingLbn
.QuadPart
= Reimagined
.StartingLbn
.QuadPart
+ Reimagined
.SectorCount
.QuadPart
;
718 return MCB_BUMP_AGAIN
;
726 FsRtlSplitBaseMcb(IN PBASE_MCB Mcb
,
731 LARGE_MCB_MAPPING_ENTRY Node
;
732 PLARGE_MCB_MAPPING_ENTRY Existing
= NULL
;
734 Node
.RunStartVbn
.QuadPart
= Vbn
;
735 Node
.SectorCount
.QuadPart
= 0;
737 Existing
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Node
);
741 // We're in the middle of a run
742 LARGE_MCB_MAPPING_ENTRY UpperPart
;
743 LARGE_MCB_MAPPING_ENTRY LowerPart
;
744 PLARGE_MCB_MAPPING_ENTRY InsertedUpper
;
746 UpperPart
.RunStartVbn
.QuadPart
= Node
.RunStartVbn
.QuadPart
+ Amount
;
747 UpperPart
.SectorCount
.QuadPart
= Existing
->RunStartVbn
.QuadPart
+
748 (Existing
->SectorCount
.QuadPart
- Node
.RunStartVbn
.QuadPart
);
749 UpperPart
.StartingLbn
.QuadPart
= Existing
->StartingLbn
.QuadPart
+
750 (Node
.RunStartVbn
.QuadPart
- Existing
->RunStartVbn
.QuadPart
);
751 LowerPart
.RunStartVbn
.QuadPart
= Existing
->RunStartVbn
.QuadPart
;
752 LowerPart
.SectorCount
.QuadPart
= Node
.RunStartVbn
.QuadPart
- Existing
->RunStartVbn
.QuadPart
;
753 LowerPart
.StartingLbn
.QuadPart
= Existing
->StartingLbn
.QuadPart
;
757 DPRINT("Loop: %x\n", Node
.RunStartVbn
.LowPart
);
758 while ((Result
= McbBump(Mcb
, &Node
)) == MCB_BUMP_AGAIN
)
760 DPRINT("Node: %x\n", Node
.RunStartVbn
.LowPart
);
764 if (Result
== MCB_BUMP_NO_MORE
)
767 RemoveHeadList(&Existing
->Sequence
);
768 RtlDeleteElementGenericTable(Mcb
->Mapping
, Existing
);
771 // Adjust the element we found.
772 Existing
->SectorCount
= LowerPart
.SectorCount
;
774 InsertedUpper
= RtlInsertElementGenericTable
775 (Mcb
->Mapping
, &UpperPart
, sizeof(UpperPart
), NULL
);
778 // Just make it like it was
779 Existing
->SectorCount
= Node
.SectorCount
;
782 InsertHeadList(GET_LIST_HEAD(Mcb
->Mapping
), &InsertedUpper
->Sequence
);
787 Node
.RunStartVbn
.QuadPart
= Vbn
;
788 Node
.SectorCount
.QuadPart
= Amount
;
789 while ((Result
= McbBump(Mcb
, &Node
)) == MCB_BUMP_AGAIN
);
790 return Result
== MCB_BUMP_NO_MORE
;
804 FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb
,
810 DPRINT("FsRtlSplitLargeMcb %x, Vbn %x, Amount %x\n", Mcb
, (ULONG
)Vbn
, (ULONG
)Amount
);
812 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
813 Result
= FsRtlSplitBaseMcb(&(Mcb
->BaseMcb
),
816 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
818 DPRINT("Done %d\n", Result
);
828 FsRtlTruncateBaseMcb(IN PBASE_MCB Mcb
,
833 FsRtlResetBaseMcb(Mcb
);
837 LARGE_MCB_MAPPING_ENTRY Truncate
;
838 PLARGE_MCB_MAPPING_ENTRY Found
;
839 Truncate
.RunStartVbn
.QuadPart
= Vbn
;
840 Truncate
.SectorCount
.QuadPart
= (1ull<<62) - Truncate
.RunStartVbn
.QuadPart
;
841 while ((Found
= RtlLookupElementGenericTable(Mcb
->Mapping
, &Truncate
)))
843 RemoveEntryList(&Found
->Sequence
);
844 RtlDeleteElementGenericTable(Mcb
->Mapping
, Found
);
855 FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb
,
858 DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb
, (ULONG
)Vbn
);
859 KeAcquireGuardedMutex(Mcb
->GuardedMutex
);
860 FsRtlTruncateBaseMcb(&(Mcb
->BaseMcb
),
862 KeReleaseGuardedMutex(Mcb
->GuardedMutex
);
871 FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb
)
873 FsRtlResetBaseMcb(Mcb
);
875 if ((Mcb
->PoolType
== PagedPool
) && (Mcb
->MaximumPairCount
== MAXIMUM_PAIR_COUNT
))
877 ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList
,
882 ExFreePoolWithTag(Mcb
->Mapping
, 'FSBC');
891 FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb
)
893 if (Mcb
->GuardedMutex
)
895 ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList
,
897 FsRtlUninitializeBaseMcb(&(Mcb
->BaseMcb
));