1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Kernel
3c2c66affSColin Finck * LICENSE: GPL v2 - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: ntoskrnl/fsrtl/largemcb.c
5c2c66affSColin Finck * PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers
6c2c66affSColin Finck * PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
7c2c66affSColin Finck * Jan Kratochvil <project-captive@jankratochvil.net>
8c2c66affSColin Finck * Trevor Thompson
9c2c66affSColin Finck */
10c2c66affSColin Finck
11c2c66affSColin Finck /* INCLUDES ******************************************************************/
12c2c66affSColin Finck
13c2c66affSColin Finck #include <ntoskrnl.h>
14c2c66affSColin Finck #define NDEBUG
15c2c66affSColin Finck #include <debug.h>
16c2c66affSColin Finck
17c2c66affSColin Finck #define MIN(x,y) (((x)<(y))?(x):(y))
18c2c66affSColin Finck #define MAX(x,y) (((x)>(y))?(x):(y))
19c2c66affSColin Finck
20c2c66affSColin Finck /* GLOBALS *******************************************************************/
21c2c66affSColin Finck
22c2c66affSColin Finck PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList;
23c2c66affSColin Finck NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList;
24c2c66affSColin Finck
25c2c66affSColin Finck /* We use only real 'mapping' runs; we do not store 'holes' to our GTree. */
26c2c66affSColin Finck typedef struct _LARGE_MCB_MAPPING_ENTRY // run
27c2c66affSColin Finck {
28c2c66affSColin Finck LARGE_INTEGER RunStartVbn;
29c2c66affSColin Finck LARGE_INTEGER RunEndVbn; /* RunStartVbn+SectorCount; that means +1 after the last sector */
30c2c66affSColin Finck LARGE_INTEGER StartingLbn; /* Lbn of 'RunStartVbn' */
31c2c66affSColin Finck } LARGE_MCB_MAPPING_ENTRY, *PLARGE_MCB_MAPPING_ENTRY;
32c2c66affSColin Finck
33c2c66affSColin Finck typedef struct _LARGE_MCB_MAPPING // mcb_priv
34c2c66affSColin Finck {
35c2c66affSColin Finck RTL_GENERIC_TABLE Table;
36c2c66affSColin Finck } LARGE_MCB_MAPPING, *PLARGE_MCB_MAPPING;
37c2c66affSColin Finck
38c2c66affSColin Finck typedef struct _BASE_MCB_INTERNAL {
39c2c66affSColin Finck ULONG MaximumPairCount;
40c2c66affSColin Finck ULONG PairCount;
41c2c66affSColin Finck USHORT PoolType;
42c2c66affSColin Finck USHORT Flags;
43c2c66affSColin Finck PLARGE_MCB_MAPPING Mapping;
44c2c66affSColin Finck } BASE_MCB_INTERNAL, *PBASE_MCB_INTERNAL;
45c2c66affSColin Finck
46c2c66affSColin Finck /*
47c2c66affSColin Finck static LARGE_MCB_MAPPING_ENTRY StaticRunBelow0 = {
48c2c66affSColin Finck {{-1}}, // ignored
49c2c66affSColin Finck {{0}},
50c2c66affSColin Finck {{-1}}, // ignored
51c2c66affSColin Finck };
52c2c66affSColin Finck */
53c2c66affSColin Finck
McbMappingAllocate(PRTL_GENERIC_TABLE Table,CLONG Bytes)54c2c66affSColin Finck static PVOID NTAPI McbMappingAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
55c2c66affSColin Finck {
56c2c66affSColin Finck PVOID Result;
57c2c66affSColin Finck PBASE_MCB Mcb = (PBASE_MCB)Table->TableContext;
583b2f1585SHermès Bélusca-Maïto Result = ExAllocatePoolWithTag(Mcb->PoolType, Bytes, 'BCML');
59c2c66affSColin Finck DPRINT("McbMappingAllocate(%lu) => %p\n", Bytes, Result);
60c2c66affSColin Finck return Result;
61c2c66affSColin Finck }
62c2c66affSColin Finck
McbMappingFree(PRTL_GENERIC_TABLE Table,PVOID Buffer)63c2c66affSColin Finck static VOID NTAPI McbMappingFree(PRTL_GENERIC_TABLE Table, PVOID Buffer)
64c2c66affSColin Finck {
65c2c66affSColin Finck DPRINT("McbMappingFree(%p)\n", Buffer);
663b2f1585SHermès Bélusca-Maïto ExFreePoolWithTag(Buffer, 'BCML');
67c2c66affSColin Finck }
68c2c66affSColin Finck
69c2c66affSColin Finck static
70c2c66affSColin Finck RTL_GENERIC_COMPARE_RESULTS
71c2c66affSColin Finck NTAPI
McbMappingCompare(PRTL_GENERIC_TABLE Table,PVOID PtrA,PVOID PtrB)72c2c66affSColin Finck McbMappingCompare(PRTL_GENERIC_TABLE Table,
73c2c66affSColin Finck PVOID PtrA,
74c2c66affSColin Finck PVOID PtrB)
75c2c66affSColin Finck {
76c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY A = PtrA, B = PtrB;
77c2c66affSColin Finck RTL_GENERIC_COMPARE_RESULTS Res;
78c2c66affSColin Finck
79c2c66affSColin Finck ASSERT(A);
80c2c66affSColin Finck ASSERT(B);
81c2c66affSColin Finck
82c2c66affSColin Finck if (A->RunStartVbn.QuadPart == B->RunStartVbn.QuadPart && A->RunEndVbn.QuadPart == B->RunEndVbn.QuadPart)
83c2c66affSColin Finck Res = GenericEqual;
84c2c66affSColin Finck else if (A->RunEndVbn.QuadPart <= B->RunStartVbn.QuadPart)
85c2c66affSColin Finck Res = GenericLessThan;
86c2c66affSColin Finck else if (A->RunEndVbn.QuadPart >= B->RunStartVbn.QuadPart)
87c2c66affSColin Finck Res = GenericGreaterThan;
88c2c66affSColin Finck else
89c2c66affSColin Finck {
90c2c66affSColin Finck ASSERT(FALSE);
91c2c66affSColin Finck Res = GenericEqual;
92c2c66affSColin Finck }
93c2c66affSColin Finck
94c2c66affSColin Finck return Res;
95c2c66affSColin Finck }
96c2c66affSColin Finck
McbMappingIntersectCompare(PRTL_GENERIC_TABLE Table,PVOID PtrA,PVOID PtrB)97c2c66affSColin Finck static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingIntersectCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
98c2c66affSColin Finck {
99c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY A = PtrA, B = PtrB;
100c2c66affSColin Finck RTL_GENERIC_COMPARE_RESULTS Res;
101c2c66affSColin Finck
102c2c66affSColin Finck if (A->RunStartVbn.QuadPart <= B->RunStartVbn.QuadPart && A->RunEndVbn.QuadPart > B->RunStartVbn.QuadPart)
103c2c66affSColin Finck Res = GenericEqual;
104c2c66affSColin Finck else if (A->RunStartVbn.QuadPart >= B->RunStartVbn.QuadPart && B->RunEndVbn.QuadPart > A->RunStartVbn.QuadPart)
105c2c66affSColin Finck Res = GenericEqual;
106c2c66affSColin Finck else if (A->RunStartVbn.QuadPart < B->RunStartVbn.QuadPart)
107c2c66affSColin Finck Res = GenericLessThan;
108c2c66affSColin Finck else if (A->RunStartVbn.QuadPart > B->RunStartVbn.QuadPart)
109c2c66affSColin Finck Res = GenericGreaterThan;
110c2c66affSColin Finck else
111c2c66affSColin Finck Res = GenericEqual;
112c2c66affSColin Finck
113c2c66affSColin Finck return Res;
114c2c66affSColin Finck }
115c2c66affSColin Finck
116c2c66affSColin Finck
117c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
118c2c66affSColin Finck
119c2c66affSColin Finck /*
120c2c66affSColin Finck * @implemented
121c2c66affSColin Finck * @Mcb: #PLARGE_MCB initialized by FsRtlInitializeLargeMcb().
122c2c66affSColin Finck * %NULL value is forbidden.
123c2c66affSColin Finck * @Vbn: Starting virtual block number of the wished range.
124c2c66affSColin Finck * @Lbn: Starting logical block number of the wished range.
125c2c66affSColin Finck * @SectorCount: Length of the wished range.
126c2c66affSColin Finck * Value less or equal to %0 is forbidden; FIXME: Is the reject of %0 W32 compliant?
127c2c66affSColin Finck *
128c2c66affSColin Finck * Adds the specified range @Vbn ... @Vbn+@SectorCount-1 to @Mcb.
129c2c66affSColin Finck * Any mappings previously in this range are deleted first.
130c2c66affSColin Finck *
131c2c66affSColin Finck * Returns: %TRUE if successful.
132c2c66affSColin Finck */
133c2c66affSColin Finck BOOLEAN
134c2c66affSColin Finck NTAPI
FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,IN LONGLONG Vbn,IN LONGLONG Lbn,IN LONGLONG SectorCount)135c2c66affSColin Finck FsRtlAddBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
136c2c66affSColin Finck IN LONGLONG Vbn,
137c2c66affSColin Finck IN LONGLONG Lbn,
138c2c66affSColin Finck IN LONGLONG SectorCount)
139c2c66affSColin Finck {
140c2c66affSColin Finck BOOLEAN Result = TRUE;
141c2c66affSColin Finck BOOLEAN IntResult;
142c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
143c2c66affSColin Finck LARGE_MCB_MAPPING_ENTRY Node, NeedleRun;
144c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY LowerRun, HigherRun;
145c2c66affSColin Finck BOOLEAN NewElement;
146*3d4cf8d2SJérôme Gardou LONGLONG IntLbn, IntSectorCount;
147c2c66affSColin Finck
148c2c66affSColin Finck DPRINT("FsRtlAddBaseMcbEntry(%p, %I64d, %I64d, %I64d)\n", OpaqueMcb, Vbn, Lbn, SectorCount);
149c2c66affSColin Finck
150c2c66affSColin Finck if (Vbn < 0)
151c2c66affSColin Finck {
152c2c66affSColin Finck Result = FALSE;
153c2c66affSColin Finck goto quit;
154c2c66affSColin Finck }
155c2c66affSColin Finck
156c2c66affSColin Finck if (SectorCount <= 0)
157c2c66affSColin Finck {
158c2c66affSColin Finck Result = FALSE;
159c2c66affSColin Finck goto quit;
160c2c66affSColin Finck }
161c2c66affSColin Finck
162*3d4cf8d2SJérôme Gardou IntResult = FsRtlLookupBaseMcbEntry(OpaqueMcb, Vbn, &IntLbn, &IntSectorCount, NULL, NULL, NULL);
163c2c66affSColin Finck if (IntResult)
164c2c66affSColin Finck {
165c2c66affSColin Finck if (IntLbn != -1 && IntLbn != Lbn)
166c2c66affSColin Finck {
167c2c66affSColin Finck Result = FALSE;
168c2c66affSColin Finck goto quit;
169c2c66affSColin Finck }
170*3d4cf8d2SJérôme Gardou
171*3d4cf8d2SJérôme Gardou if ((IntLbn != -1) && (IntSectorCount >= SectorCount))
172*3d4cf8d2SJérôme Gardou {
173*3d4cf8d2SJérôme Gardou /* This is a no-op */
174*3d4cf8d2SJérôme Gardou goto quit;
175*3d4cf8d2SJérôme Gardou }
176c2c66affSColin Finck }
177c2c66affSColin Finck
178c2c66affSColin Finck /* clean any possible previous entries in our range */
179c2c66affSColin Finck FsRtlRemoveBaseMcbEntry(OpaqueMcb, Vbn, SectorCount);
180c2c66affSColin Finck
181c2c66affSColin Finck // We need to map [Vbn, Vbn+SectorCount) to [Lbn, Lbn+SectorCount),
182c2c66affSColin Finck // taking in account the fact that we need to merge these runs if
183c2c66affSColin Finck // they are adjacent or overlap, but fail if new run fully fits into another run
184c2c66affSColin Finck
185c2c66affSColin Finck /* initially we think we will be inserted as a separate run */
186c2c66affSColin Finck Node.RunStartVbn.QuadPart = Vbn;
187c2c66affSColin Finck Node.RunEndVbn.QuadPart = Vbn + SectorCount;
188c2c66affSColin Finck Node.StartingLbn.QuadPart = Lbn;
189c2c66affSColin Finck
190c2c66affSColin Finck /* optionally merge with lower run */
191c2c66affSColin Finck NeedleRun.RunStartVbn.QuadPart = Node.RunStartVbn.QuadPart - 1;
192c2c66affSColin Finck NeedleRun.RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart + 1;
193c2c66affSColin Finck NeedleRun.StartingLbn.QuadPart = ~0ULL;
194c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
195c2c66affSColin Finck if ((LowerRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)) &&
196c2c66affSColin Finck (LowerRun->StartingLbn.QuadPart + (LowerRun->RunEndVbn.QuadPart - LowerRun->RunStartVbn.QuadPart) == Node.StartingLbn.QuadPart))
197c2c66affSColin Finck {
198c2c66affSColin Finck ASSERT(LowerRun->RunEndVbn.QuadPart == Node.RunStartVbn.QuadPart);
199c2c66affSColin Finck Node.RunStartVbn.QuadPart = LowerRun->RunStartVbn.QuadPart;
200c2c66affSColin Finck Node.StartingLbn.QuadPart = LowerRun->StartingLbn.QuadPart;
201c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
202c2c66affSColin Finck RtlDeleteElementGenericTable(&Mcb->Mapping->Table, LowerRun);
203c2c66affSColin Finck --Mcb->PairCount;
204c2c66affSColin Finck DPRINT("Intersecting lower run found (%I64d,%I64d) Lbn: %I64d\n", LowerRun->RunStartVbn.QuadPart, LowerRun->RunEndVbn.QuadPart, LowerRun->StartingLbn.QuadPart);
205c2c66affSColin Finck }
206c2c66affSColin Finck
207c2c66affSColin Finck /* optionally merge with higher run */
208c2c66affSColin Finck NeedleRun.RunStartVbn.QuadPart = Node.RunEndVbn.QuadPart;
209c2c66affSColin Finck NeedleRun.RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart + 1;
210c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
211c2c66affSColin Finck if ((HigherRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)) &&
212c2c66affSColin Finck (Node.StartingLbn.QuadPart <= HigherRun->StartingLbn.QuadPart))
213c2c66affSColin Finck {
214c2c66affSColin Finck ASSERT(HigherRun->RunStartVbn.QuadPart == Node.RunEndVbn.QuadPart);
215c2c66affSColin Finck Node.RunEndVbn.QuadPart = HigherRun->RunEndVbn.QuadPart;
216c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
217c2c66affSColin Finck RtlDeleteElementGenericTable(&Mcb->Mapping->Table, HigherRun);
218c2c66affSColin Finck --Mcb->PairCount;
219c2c66affSColin Finck DPRINT("Intersecting higher run found (%I64d,%I64d) Lbn: %I64d\n", HigherRun->RunStartVbn.QuadPart, HigherRun->RunEndVbn.QuadPart, HigherRun->StartingLbn.QuadPart);
220c2c66affSColin Finck }
221c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
222c2c66affSColin Finck
223c2c66affSColin Finck /* finally insert the resulting run */
224c2c66affSColin Finck RtlInsertElementGenericTable(&Mcb->Mapping->Table, &Node, sizeof(Node), &NewElement);
225c2c66affSColin Finck ++Mcb->PairCount;
226c2c66affSColin Finck ASSERT(NewElement);
227c2c66affSColin Finck
228c2c66affSColin Finck // NB: Two consecutive runs can only be merged, if actual LBNs also match!
229c2c66affSColin Finck
230c2c66affSColin Finck /* 1.
231c2c66affSColin Finck Existing->RunStartVbn
232c2c66affSColin Finck |
233c2c66affSColin Finck |///////|
234c2c66affSColin Finck |/////////////|
235c2c66affSColin Finck |
236c2c66affSColin Finck Node->RunStartVbn
237c2c66affSColin Finck
238c2c66affSColin Finck 2.
239c2c66affSColin Finck Existing->RunStartVbn
240c2c66affSColin Finck |
241c2c66affSColin Finck |///////|
242c2c66affSColin Finck |//////|
243c2c66affSColin Finck |
244c2c66affSColin Finck Node->RunStartVbn
245c2c66affSColin Finck
246c2c66affSColin Finck 3.
247c2c66affSColin Finck Existing->RunStartVbn
248c2c66affSColin Finck |
249c2c66affSColin Finck |///////|
250c2c66affSColin Finck |///|
251c2c66affSColin Finck |
252c2c66affSColin Finck Node->RunStartVbn
253c2c66affSColin Finck
254c2c66affSColin Finck 4.
255c2c66affSColin Finck Existing->RunStartVbn
256c2c66affSColin Finck |
257c2c66affSColin Finck |///////|
258c2c66affSColin Finck |///////////////|
259c2c66affSColin Finck |
260c2c66affSColin Finck Node->RunStartVbn
261c2c66affSColin Finck
262c2c66affSColin Finck
263c2c66affSColin Finck Situation with holes:
264c2c66affSColin Finck 1. Holes at both ends
265c2c66affSColin Finck 2. Hole at the right, new run merged with the previous run
266c2c66affSColin Finck 3. Hole at the right, new run is not merged with the previous run
267c2c66affSColin Finck 4. Hole at the left, new run merged with the next run
268c2c66affSColin Finck 5. Hole at the left, new run is not merged with the next run
269c2c66affSColin Finck 6. No holes, exact fit to merge with both previous and next runs
270c2c66affSColin Finck 7. No holes, merges only with the next run
271c2c66affSColin Finck 8. No holes, merges only with the previous run
272c2c66affSColin Finck 9. No holes, does not merge with next or prev runs
273c2c66affSColin Finck
274c2c66affSColin Finck
275c2c66affSColin Finck Overwriting existing mapping is not possible and results in FALSE being returned
276c2c66affSColin Finck */
277c2c66affSColin Finck
278c2c66affSColin Finck quit:
279c2c66affSColin Finck DPRINT("FsRtlAddBaseMcbEntry(%p, %I64d, %I64d, %I64d) = %d\n", Mcb, Vbn, Lbn, SectorCount, Result);
280c2c66affSColin Finck return Result;
281c2c66affSColin Finck }
282c2c66affSColin Finck
283c2c66affSColin Finck /*
284c2c66affSColin Finck * @implemented
285c2c66affSColin Finck */
286c2c66affSColin Finck BOOLEAN
287c2c66affSColin Finck NTAPI
FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb,IN LONGLONG Vbn,IN LONGLONG Lbn,IN LONGLONG SectorCount)288c2c66affSColin Finck FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb,
289c2c66affSColin Finck IN LONGLONG Vbn,
290c2c66affSColin Finck IN LONGLONG Lbn,
291c2c66affSColin Finck IN LONGLONG SectorCount)
292c2c66affSColin Finck {
293c2c66affSColin Finck BOOLEAN Result;
294c2c66affSColin Finck
295c2c66affSColin Finck DPRINT("FsRtlAddLargeMcbEntry(%p, %I64d, %I64d, %I64d)\n", Mcb, Vbn, Lbn, SectorCount);
296c2c66affSColin Finck
297c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
298c2c66affSColin Finck Result = FsRtlAddBaseMcbEntry(&(Mcb->BaseMcb),
299c2c66affSColin Finck Vbn,
300c2c66affSColin Finck Lbn,
301c2c66affSColin Finck SectorCount);
302c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
303c2c66affSColin Finck
304c2c66affSColin Finck DPRINT("FsRtlAddLargeMcbEntry(%p, %I64d, %I64d, %I64d) = %d\n", Mcb, Vbn, Lbn, SectorCount, Result);
305c2c66affSColin Finck
306c2c66affSColin Finck return Result;
307c2c66affSColin Finck }
308c2c66affSColin Finck
309c2c66affSColin Finck /*
310c2c66affSColin Finck * @implemented
311c2c66affSColin Finck * @Mcb: #PLARGE_MCB initialized by FsRtlInitializeLargeMcb().
312c2c66affSColin Finck * %NULL value is forbidden.
313c2c66affSColin Finck * @RunIndex: Requested range index to retrieve.
314c2c66affSColin Finck * @Vbn: Returns the starting virtual block number of the wished range.
315c2c66affSColin Finck * %NULL pointer is forbidden.
316c2c66affSColin Finck * @Lbn: Returns the starting logical block number of the wished range (or -1 if it is a hole).
317c2c66affSColin Finck * %NULL pointer is forbidden.
318c2c66affSColin Finck * @SectorCount: Returns the length of the wished range.
319c2c66affSColin Finck * %NULL pointer is forbidden.
320c2c66affSColin Finck * Value less or equal to %0 is forbidden; FIXME: Is the reject of %0 W32 compliant?
321c2c66affSColin Finck *
322c2c66affSColin Finck * Retrieves the parameters of the specified run with index @RunIndex.
323c2c66affSColin Finck *
324c2c66affSColin Finck * Mapping %0 always starts at virtual block %0, either as 'hole' or as 'real' mapping.
325c2c66affSColin Finck * libcaptive does not store 'hole' information to its #GTree.
326c2c66affSColin Finck * Last run is always a 'real' run. 'hole' runs appear as mapping to constant @Lbn value %-1.
327c2c66affSColin Finck *
328c2c66affSColin Finck * Returns: %TRUE if successful.
329c2c66affSColin Finck */
330c2c66affSColin Finck BOOLEAN
331c2c66affSColin Finck NTAPI
FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb,IN ULONG RunIndex,OUT PLONGLONG Vbn,OUT PLONGLONG Lbn,OUT PLONGLONG SectorCount)332c2c66affSColin Finck FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
333c2c66affSColin Finck IN ULONG RunIndex,
334c2c66affSColin Finck OUT PLONGLONG Vbn,
335c2c66affSColin Finck OUT PLONGLONG Lbn,
336c2c66affSColin Finck OUT PLONGLONG SectorCount)
337c2c66affSColin Finck {
338c2c66affSColin Finck BOOLEAN Result = FALSE;
339c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
340c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY Run = NULL;
341c2c66affSColin Finck ULONG CurrentIndex = 0;
342c2c66affSColin Finck ULONGLONG LastVbn = 0;
343c2c66affSColin Finck ULONGLONG LastSectorCount = 0;
344c2c66affSColin Finck
345c2c66affSColin Finck // Traverse the tree
346c2c66affSColin Finck for (Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
347c2c66affSColin Finck Run;
348c2c66affSColin Finck Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
349c2c66affSColin Finck {
350c2c66affSColin Finck // is the current index a hole?
351c2c66affSColin Finck if (Run->RunStartVbn.QuadPart > (LastVbn + LastSectorCount))
352c2c66affSColin Finck {
353c2c66affSColin Finck // Is this the index we're looking for?
354c2c66affSColin Finck if (RunIndex == CurrentIndex)
355c2c66affSColin Finck {
356c2c66affSColin Finck *Vbn = LastVbn + LastSectorCount;
357c2c66affSColin Finck *Lbn = -1;
358c2c66affSColin Finck *SectorCount = Run->RunStartVbn.QuadPart - *Vbn;
359c2c66affSColin Finck
360c2c66affSColin Finck Result = TRUE;
361c2c66affSColin Finck goto quit;
362c2c66affSColin Finck }
363c2c66affSColin Finck
364c2c66affSColin Finck CurrentIndex++;
365c2c66affSColin Finck }
366c2c66affSColin Finck
367c2c66affSColin Finck if (RunIndex == CurrentIndex)
368c2c66affSColin Finck {
369c2c66affSColin Finck *Vbn = Run->RunStartVbn.QuadPart;
370c2c66affSColin Finck *Lbn = Run->StartingLbn.QuadPart;
371c2c66affSColin Finck *SectorCount = Run->RunEndVbn.QuadPart - Run->RunStartVbn.QuadPart;
372c2c66affSColin Finck
373c2c66affSColin Finck Result = TRUE;
374c2c66affSColin Finck goto quit;
375c2c66affSColin Finck }
376c2c66affSColin Finck
377c2c66affSColin Finck CurrentIndex++;
378c2c66affSColin Finck LastVbn = Run->RunStartVbn.QuadPart;
379c2c66affSColin Finck LastSectorCount = Run->RunEndVbn.QuadPart - Run->RunStartVbn.QuadPart;
380c2c66affSColin Finck }
381c2c66affSColin Finck
382c2c66affSColin Finck quit:
383c2c66affSColin Finck DPRINT("FsRtlGetNextBaseMcbEntry(%p, %d, %p, %p, %p) = %d (%I64d, %I64d, %I64d)\n", Mcb, RunIndex, Vbn, Lbn, SectorCount, Result, *Vbn, *Lbn, *SectorCount);
384c2c66affSColin Finck return Result;
385c2c66affSColin Finck }
386c2c66affSColin Finck
387c2c66affSColin Finck /*
388c2c66affSColin Finck * @implemented
389c2c66affSColin Finck */
390c2c66affSColin Finck BOOLEAN
391c2c66affSColin Finck NTAPI
FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb,IN ULONG RunIndex,OUT PLONGLONG Vbn,OUT PLONGLONG Lbn,OUT PLONGLONG SectorCount)392c2c66affSColin Finck FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb,
393c2c66affSColin Finck IN ULONG RunIndex,
394c2c66affSColin Finck OUT PLONGLONG Vbn,
395c2c66affSColin Finck OUT PLONGLONG Lbn,
396c2c66affSColin Finck OUT PLONGLONG SectorCount)
397c2c66affSColin Finck {
398c2c66affSColin Finck BOOLEAN Result;
399c2c66affSColin Finck
400c2c66affSColin Finck DPRINT("FsRtlGetNextLargeMcbEntry(%p, %d, %p, %p, %p)\n", Mcb, RunIndex, Vbn, Lbn, SectorCount);
401c2c66affSColin Finck
402c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
403c2c66affSColin Finck Result = FsRtlGetNextBaseMcbEntry(&(Mcb->BaseMcb),
404c2c66affSColin Finck RunIndex,
405c2c66affSColin Finck Vbn,
406c2c66affSColin Finck Lbn,
407c2c66affSColin Finck SectorCount);
408c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
409c2c66affSColin Finck
410c2c66affSColin Finck DPRINT("FsRtlGetNextLargeMcbEntry(%p, %d, %p, %p, %p) = %d (%I64d, %I64d, %I64d)\n", Mcb, RunIndex, Vbn, Lbn, SectorCount, Result, *Vbn, *Lbn, *SectorCount);
411c2c66affSColin Finck
412c2c66affSColin Finck return Result;
413c2c66affSColin Finck }
414c2c66affSColin Finck
415c2c66affSColin Finck /*
416c2c66affSColin Finck * @implemented
417c2c66affSColin Finck */
418c2c66affSColin Finck VOID
419c2c66affSColin Finck NTAPI
FsRtlInitializeBaseMcb(IN PBASE_MCB OpaqueMcb,IN POOL_TYPE PoolType)420c2c66affSColin Finck FsRtlInitializeBaseMcb(IN PBASE_MCB OpaqueMcb,
421c2c66affSColin Finck IN POOL_TYPE PoolType)
422c2c66affSColin Finck {
423c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
424c2c66affSColin Finck
425c2c66affSColin Finck if (PoolType == PagedPool)
426c2c66affSColin Finck {
427c2c66affSColin Finck Mcb->Mapping = ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList);
428c2c66affSColin Finck }
429c2c66affSColin Finck else
430c2c66affSColin Finck {
431c2c66affSColin Finck Mcb->Mapping = ExAllocatePoolWithTag(PoolType | POOL_RAISE_IF_ALLOCATION_FAILURE,
432c2c66affSColin Finck sizeof(LARGE_MCB_MAPPING),
4333b2f1585SHermès Bélusca-Maïto 'CBSF');
434c2c66affSColin Finck }
435c2c66affSColin Finck
436c2c66affSColin Finck Mcb->PoolType = PoolType;
437c2c66affSColin Finck Mcb->PairCount = 0;
438c2c66affSColin Finck Mcb->MaximumPairCount = MAXIMUM_PAIR_COUNT;
439c2c66affSColin Finck RtlInitializeGenericTable(&Mcb->Mapping->Table,
440c2c66affSColin Finck McbMappingCompare,
441c2c66affSColin Finck McbMappingAllocate,
442c2c66affSColin Finck McbMappingFree,
443c2c66affSColin Finck Mcb);
444c2c66affSColin Finck }
445c2c66affSColin Finck
446c2c66affSColin Finck /*
447c2c66affSColin Finck * @implemented
448c2c66affSColin Finck */
449c2c66affSColin Finck VOID
450c2c66affSColin Finck NTAPI
FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb,IN POOL_TYPE PoolType)451c2c66affSColin Finck FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb,
452c2c66affSColin Finck IN POOL_TYPE PoolType)
453c2c66affSColin Finck {
454c2c66affSColin Finck DPRINT("FsRtlInitializeLargeMcb(%p, %d)\n", Mcb, PoolType);
455c2c66affSColin Finck
456c2c66affSColin Finck Mcb->GuardedMutex = ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList);
457c2c66affSColin Finck
458c2c66affSColin Finck KeInitializeGuardedMutex(Mcb->GuardedMutex);
459c2c66affSColin Finck
460c2c66affSColin Finck _SEH2_TRY
461c2c66affSColin Finck {
462c2c66affSColin Finck FsRtlInitializeBaseMcb(&(Mcb->BaseMcb), PoolType);
463c2c66affSColin Finck }
464c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
465c2c66affSColin Finck {
466c2c66affSColin Finck ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList,
467c2c66affSColin Finck Mcb->GuardedMutex);
468c2c66affSColin Finck Mcb->GuardedMutex = NULL;
469c2c66affSColin Finck }
470c2c66affSColin Finck _SEH2_END;
471c2c66affSColin Finck }
472c2c66affSColin Finck
473c2c66affSColin Finck /*
474c2c66affSColin Finck * @implemented
475c2c66affSColin Finck */
4765c7ce447SVictor Perevertkin CODE_SEG("INIT")
477c2c66affSColin Finck VOID
478c2c66affSColin Finck NTAPI
FsRtlInitializeLargeMcbs(VOID)479c2c66affSColin Finck FsRtlInitializeLargeMcbs(VOID)
480c2c66affSColin Finck {
481c2c66affSColin Finck /* Initialize the list for the MCB */
482c2c66affSColin Finck ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList,
483c2c66affSColin Finck NULL,
484c2c66affSColin Finck NULL,
485c2c66affSColin Finck POOL_RAISE_IF_ALLOCATION_FAILURE,
486c2c66affSColin Finck sizeof(LARGE_MCB_MAPPING),
487c2c66affSColin Finck IFS_POOL_TAG,
488c2c66affSColin Finck 0); /* FIXME: Should be 4 */
489c2c66affSColin Finck
490c2c66affSColin Finck /* Initialize the list for the guarded mutex */
491c2c66affSColin Finck ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList,
492c2c66affSColin Finck NULL,
493c2c66affSColin Finck NULL,
494c2c66affSColin Finck POOL_RAISE_IF_ALLOCATION_FAILURE,
495c2c66affSColin Finck sizeof(KGUARDED_MUTEX),
496c2c66affSColin Finck IFS_POOL_TAG,
497c2c66affSColin Finck 0); /* FIXME: Should be 32 */
498c2c66affSColin Finck }
499c2c66affSColin Finck
500c2c66affSColin Finck /*
501c2c66affSColin Finck * @implemented
502c2c66affSColin Finck */
503c2c66affSColin Finck BOOLEAN
504c2c66affSColin Finck NTAPI
FsRtlLookupBaseMcbEntry(IN PBASE_MCB OpaqueMcb,IN LONGLONG Vbn,OUT PLONGLONG Lbn OPTIONAL,OUT PLONGLONG SectorCountFromLbn OPTIONAL,OUT PLONGLONG StartingLbn OPTIONAL,OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,OUT PULONG Index OPTIONAL)505c2c66affSColin Finck FsRtlLookupBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
506c2c66affSColin Finck IN LONGLONG Vbn,
507c2c66affSColin Finck OUT PLONGLONG Lbn OPTIONAL,
508c2c66affSColin Finck OUT PLONGLONG SectorCountFromLbn OPTIONAL,
509c2c66affSColin Finck OUT PLONGLONG StartingLbn OPTIONAL,
510c2c66affSColin Finck OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,
511c2c66affSColin Finck OUT PULONG Index OPTIONAL)
512c2c66affSColin Finck {
513c2c66affSColin Finck BOOLEAN Result = FALSE;
514c2c66affSColin Finck ULONG i;
515c2c66affSColin Finck LONGLONG LastVbn = 0, LastLbn = 0, Count = 0; // the last values we've found during traversal
516c2c66affSColin Finck
517c2c66affSColin Finck DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p)\n", OpaqueMcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, SectorCountFromStartingLbn, Index);
518c2c66affSColin Finck
519c2c66affSColin Finck for (i = 0; FsRtlGetNextBaseMcbEntry(OpaqueMcb, i, &LastVbn, &LastLbn, &Count); i++)
520c2c66affSColin Finck {
521c2c66affSColin Finck // have we reached the target mapping?
522c2c66affSColin Finck if (Vbn < LastVbn + Count)
523c2c66affSColin Finck {
524c2c66affSColin Finck if (Lbn)
525c2c66affSColin Finck {
526c2c66affSColin Finck if (LastLbn == -1)
527c2c66affSColin Finck *Lbn = -1;
528c2c66affSColin Finck else
529c2c66affSColin Finck *Lbn = LastLbn + (Vbn - LastVbn);
530c2c66affSColin Finck }
531c2c66affSColin Finck
532c2c66affSColin Finck if (SectorCountFromLbn)
533c2c66affSColin Finck *SectorCountFromLbn = LastVbn + Count - Vbn;
534c2c66affSColin Finck if (StartingLbn)
535c2c66affSColin Finck *StartingLbn = LastLbn;
536c2c66affSColin Finck if (SectorCountFromStartingLbn)
537c2c66affSColin Finck *SectorCountFromStartingLbn = LastVbn + Count - LastVbn;
538c2c66affSColin Finck if (Index)
539c2c66affSColin Finck *Index = i;
540c2c66affSColin Finck
541c2c66affSColin Finck Result = TRUE;
542c2c66affSColin Finck goto quit;
543c2c66affSColin Finck }
544c2c66affSColin Finck }
545c2c66affSColin Finck
546c2c66affSColin Finck quit:
547c2c66affSColin Finck DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p) = %d (%I64d, %I64d, %I64d, %I64d, %d)\n",
548c2c66affSColin Finck OpaqueMcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, SectorCountFromStartingLbn, Index, Result,
549c2c66affSColin Finck (Lbn ? *Lbn : (ULONGLONG)-1), (SectorCountFromLbn ? *SectorCountFromLbn : (ULONGLONG)-1), (StartingLbn ? *StartingLbn : (ULONGLONG)-1),
550c2c66affSColin Finck (SectorCountFromStartingLbn ? *SectorCountFromStartingLbn : (ULONGLONG)-1), (Index ? *Index : (ULONG)-1));
551c2c66affSColin Finck
552c2c66affSColin Finck return Result;
553c2c66affSColin Finck }
554c2c66affSColin Finck
555c2c66affSColin Finck /*
556c2c66affSColin Finck * @implemented
557c2c66affSColin Finck */
558c2c66affSColin Finck BOOLEAN
559c2c66affSColin Finck NTAPI
FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb,IN LONGLONG Vbn,OUT PLONGLONG Lbn OPTIONAL,OUT PLONGLONG SectorCountFromLbn OPTIONAL,OUT PLONGLONG StartingLbn OPTIONAL,OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,OUT PULONG Index OPTIONAL)560c2c66affSColin Finck FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb,
561c2c66affSColin Finck IN LONGLONG Vbn,
562c2c66affSColin Finck OUT PLONGLONG Lbn OPTIONAL,
563c2c66affSColin Finck OUT PLONGLONG SectorCountFromLbn OPTIONAL,
564c2c66affSColin Finck OUT PLONGLONG StartingLbn OPTIONAL,
565c2c66affSColin Finck OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,
566c2c66affSColin Finck OUT PULONG Index OPTIONAL)
567c2c66affSColin Finck {
568c2c66affSColin Finck BOOLEAN Result;
569c2c66affSColin Finck
570c2c66affSColin Finck DPRINT("FsRtlLookupLargeMcbEntry(%p, %I64d, %p, %p, %p, %p, %p)\n", Mcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, SectorCountFromStartingLbn, Index);
571c2c66affSColin Finck
572c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
573c2c66affSColin Finck Result = FsRtlLookupBaseMcbEntry(&(Mcb->BaseMcb),
574c2c66affSColin Finck Vbn,
575c2c66affSColin Finck Lbn,
576c2c66affSColin Finck SectorCountFromLbn,
577c2c66affSColin Finck StartingLbn,
578c2c66affSColin Finck SectorCountFromStartingLbn,
579c2c66affSColin Finck Index);
580c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
581c2c66affSColin Finck
582c2c66affSColin Finck DPRINT("FsRtlLookupLargeMcbEntry(%p, %I64d, %p, %p, %p, %p, %p) = %d (%I64d, %I64d, %I64d, %I64d, %d)\n",
583c2c66affSColin Finck Mcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, SectorCountFromStartingLbn, Index, Result,
584c2c66affSColin Finck (Lbn ? *Lbn : (ULONGLONG)-1), (SectorCountFromLbn ? *SectorCountFromLbn : (ULONGLONG)-1), (StartingLbn ? *StartingLbn : (ULONGLONG)-1),
585c2c66affSColin Finck (SectorCountFromStartingLbn ? *SectorCountFromStartingLbn : (ULONGLONG)-1), (Index ? *Index : (ULONG)-1));
586c2c66affSColin Finck
587c2c66affSColin Finck return Result;
588c2c66affSColin Finck }
589c2c66affSColin Finck
590c2c66affSColin Finck static BOOLEAN
591c2c66affSColin Finck NTAPI
FsRtlLookupLastLargeMcbEntryAndIndex_internal(IN PBASE_MCB_INTERNAL Mcb,OUT PLONGLONG Vbn,OUT PLONGLONG Lbn,OUT PULONG Index OPTIONAL)592c2c66affSColin Finck FsRtlLookupLastLargeMcbEntryAndIndex_internal(IN PBASE_MCB_INTERNAL Mcb,
593c2c66affSColin Finck OUT PLONGLONG Vbn,
594c2c66affSColin Finck OUT PLONGLONG Lbn,
595c2c66affSColin Finck OUT PULONG Index OPTIONAL)
596c2c66affSColin Finck {
597c2c66affSColin Finck ULONG RunIndex = 0;
598c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY Run, RunFound = NULL;
599c2c66affSColin Finck LONGLONG LastVbn = 0;
600c2c66affSColin Finck
601c2c66affSColin Finck for (Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
602c2c66affSColin Finck Run;
603c2c66affSColin Finck Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
604c2c66affSColin Finck {
605c2c66affSColin Finck /* Take care when we must emulate missing 'hole' runs. */
606c2c66affSColin Finck if (Run->RunStartVbn.QuadPart > LastVbn)
607c2c66affSColin Finck {
608c2c66affSColin Finck RunIndex++;
609c2c66affSColin Finck }
610c2c66affSColin Finck LastVbn = Run->RunEndVbn.QuadPart;
611c2c66affSColin Finck RunIndex++;
612c2c66affSColin Finck RunFound = Run;
613c2c66affSColin Finck }
614c2c66affSColin Finck
615c2c66affSColin Finck if (!RunFound)
616c2c66affSColin Finck {
617c2c66affSColin Finck return FALSE;
618c2c66affSColin Finck }
619c2c66affSColin Finck
620c2c66affSColin Finck if (Vbn)
621c2c66affSColin Finck {
622c2c66affSColin Finck *Vbn = RunFound->RunEndVbn.QuadPart - 1;
623c2c66affSColin Finck }
624c2c66affSColin Finck if (Lbn)
625c2c66affSColin Finck {
626c2c66affSColin Finck if (1)
627c2c66affSColin Finck {
628c2c66affSColin Finck *Lbn = RunFound->StartingLbn.QuadPart + (RunFound->RunEndVbn.QuadPart - RunFound->RunStartVbn.QuadPart) - 1;
629c2c66affSColin Finck }
630c2c66affSColin Finck else
631c2c66affSColin Finck {
632c2c66affSColin Finck *Lbn = ~0ULL;
633c2c66affSColin Finck }
634c2c66affSColin Finck }
635c2c66affSColin Finck if (Index)
636c2c66affSColin Finck {
637c2c66affSColin Finck *Index = RunIndex - 1;
638c2c66affSColin Finck }
639c2c66affSColin Finck
640c2c66affSColin Finck return TRUE;
641c2c66affSColin Finck }
642c2c66affSColin Finck
643c2c66affSColin Finck
644c2c66affSColin Finck /*
645c2c66affSColin Finck * @implemented
646c2c66affSColin Finck */
647c2c66affSColin Finck BOOLEAN
648c2c66affSColin Finck NTAPI
FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb,IN OUT PLONGLONG LargeVbn,IN OUT PLONGLONG LargeLbn,IN OUT PULONG Index)649c2c66affSColin Finck FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb,
650c2c66affSColin Finck IN OUT PLONGLONG LargeVbn,
651c2c66affSColin Finck IN OUT PLONGLONG LargeLbn,
652c2c66affSColin Finck IN OUT PULONG Index)
653c2c66affSColin Finck {
654c2c66affSColin Finck BOOLEAN Result;
655c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
656c2c66affSColin Finck
657c2c66affSColin Finck DPRINT("FsRtlLookupLastBaseMcbEntryAndIndex(%p, %p, %p, %p)\n", OpaqueMcb, LargeVbn, LargeLbn, Index);
658c2c66affSColin Finck
659c2c66affSColin Finck Result = FsRtlLookupLastLargeMcbEntryAndIndex_internal(Mcb, LargeVbn, LargeLbn, Index);
660c2c66affSColin Finck
661c2c66affSColin Finck DPRINT("FsRtlLookupLastBaseMcbEntryAndIndex(%p, %p, %p, %p) = %d (%I64d, %I64d, %d)\n", OpaqueMcb, LargeVbn, LargeLbn, Index, Result, *LargeVbn, *LargeLbn, *Index);
662c2c66affSColin Finck
663c2c66affSColin Finck return Result;
664c2c66affSColin Finck }
665c2c66affSColin Finck
666c2c66affSColin Finck /*
667c2c66affSColin Finck * @implemented
668c2c66affSColin Finck */
669c2c66affSColin Finck BOOLEAN
670c2c66affSColin Finck NTAPI
FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb,OUT PLONGLONG LargeVbn,OUT PLONGLONG LargeLbn,OUT PULONG Index)671c2c66affSColin Finck FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb,
672c2c66affSColin Finck OUT PLONGLONG LargeVbn,
673c2c66affSColin Finck OUT PLONGLONG LargeLbn,
674c2c66affSColin Finck OUT PULONG Index)
675c2c66affSColin Finck {
676c2c66affSColin Finck BOOLEAN Result;
677c2c66affSColin Finck
678c2c66affSColin Finck DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex(%p, %p, %p, %p)\n", OpaqueMcb, LargeVbn, LargeLbn, Index);
679c2c66affSColin Finck
680c2c66affSColin Finck KeAcquireGuardedMutex(OpaqueMcb->GuardedMutex);
681c2c66affSColin Finck Result = FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb->BaseMcb),
682c2c66affSColin Finck LargeVbn,
683c2c66affSColin Finck LargeLbn,
684c2c66affSColin Finck Index);
685c2c66affSColin Finck KeReleaseGuardedMutex(OpaqueMcb->GuardedMutex);
686c2c66affSColin Finck
687c2c66affSColin Finck DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex(%p, %p, %p, %p) = %d (%I64d, %I64d, %d)\n", OpaqueMcb, LargeVbn, LargeLbn, Index, Result, *LargeVbn, *LargeLbn, *Index);
688c2c66affSColin Finck
689c2c66affSColin Finck return Result;
690c2c66affSColin Finck }
691c2c66affSColin Finck
692c2c66affSColin Finck /*
693c2c66affSColin Finck * @unimplemented
694c2c66affSColin Finck */
695c2c66affSColin Finck BOOLEAN
696c2c66affSColin Finck NTAPI
FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB OpaqueMcb,OUT PLONGLONG Vbn,OUT PLONGLONG Lbn)697c2c66affSColin Finck FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
698c2c66affSColin Finck OUT PLONGLONG Vbn,
699c2c66affSColin Finck OUT PLONGLONG Lbn)
700c2c66affSColin Finck {
701c2c66affSColin Finck BOOLEAN Result;
702c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
703c2c66affSColin Finck
704c2c66affSColin Finck DPRINT("FsRtlLookupLastBaseMcbEntry(%p, %p, %p)\n", OpaqueMcb, Vbn, Lbn);
705c2c66affSColin Finck
706c2c66affSColin Finck Result = FsRtlLookupLastLargeMcbEntryAndIndex_internal(Mcb, Vbn, Lbn, NULL); /* Index */
707c2c66affSColin Finck
708c2c66affSColin Finck DPRINT("FsRtlLookupLastBaseMcbEntry(%p, %p, %p) = %d (%I64d, %I64d)\n", Mcb, Vbn, Lbn, Result, *Vbn, *Lbn);
709c2c66affSColin Finck
710c2c66affSColin Finck return Result;
711c2c66affSColin Finck }
712c2c66affSColin Finck
713c2c66affSColin Finck /*
714c2c66affSColin Finck * @implemented
715c2c66affSColin Finck */
716c2c66affSColin Finck BOOLEAN
717c2c66affSColin Finck NTAPI
FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb,OUT PLONGLONG Vbn,OUT PLONGLONG Lbn)718c2c66affSColin Finck FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb,
719c2c66affSColin Finck OUT PLONGLONG Vbn,
720c2c66affSColin Finck OUT PLONGLONG Lbn)
721c2c66affSColin Finck {
722c2c66affSColin Finck BOOLEAN Result;
723c2c66affSColin Finck
724c2c66affSColin Finck DPRINT("FsRtlLookupLastLargeMcbEntry(%p, %p, %p)\n", Mcb, Vbn, Lbn);
725c2c66affSColin Finck
726c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
727c2c66affSColin Finck Result = FsRtlLookupLastBaseMcbEntry(&(Mcb->BaseMcb),
728c2c66affSColin Finck Vbn,
729c2c66affSColin Finck Lbn);
730c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
731c2c66affSColin Finck
732c2c66affSColin Finck DPRINT("FsRtlLookupLastLargeMcbEntry(%p, %p, %p) = %d (%I64d, %I64d)\n", Mcb, Vbn, Lbn, Result, *Vbn, *Lbn);
733c2c66affSColin Finck
734c2c66affSColin Finck return Result;
735c2c66affSColin Finck }
736c2c66affSColin Finck
737c2c66affSColin Finck /*
738c2c66affSColin Finck * @implemented
739c2c66affSColin Finck */
740c2c66affSColin Finck ULONG
741c2c66affSColin Finck NTAPI
FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb)742c2c66affSColin Finck FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb)
743c2c66affSColin Finck {
744c2c66affSColin Finck ULONG NumberOfRuns = 0;
745c2c66affSColin Finck LONGLONG Vbn, Lbn, Count;
746c2c66affSColin Finck int i;
747c2c66affSColin Finck
748c2c66affSColin Finck DPRINT("FsRtlNumberOfRunsInBaseMcb(%p)\n", OpaqueMcb);
749c2c66affSColin Finck
750c2c66affSColin Finck // Count how many Mcb entries there are
751c2c66affSColin Finck for (i = 0; FsRtlGetNextBaseMcbEntry(OpaqueMcb, i, &Vbn, &Lbn, &Count); i++)
752c2c66affSColin Finck {
753c2c66affSColin Finck NumberOfRuns++;
754c2c66affSColin Finck }
755c2c66affSColin Finck
756c2c66affSColin Finck DPRINT("FsRtlNumberOfRunsInBaseMcb(%p) = %d\n", OpaqueMcb, NumberOfRuns);
757c2c66affSColin Finck return NumberOfRuns;
758c2c66affSColin Finck }
759c2c66affSColin Finck
760c2c66affSColin Finck /*
761c2c66affSColin Finck * @implemented
762c2c66affSColin Finck */
763c2c66affSColin Finck ULONG
764c2c66affSColin Finck NTAPI
FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb)765c2c66affSColin Finck FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb)
766c2c66affSColin Finck {
767c2c66affSColin Finck ULONG NumberOfRuns;
768c2c66affSColin Finck
769c2c66affSColin Finck DPRINT("FsRtlNumberOfRunsInLargeMcb(%p)\n", Mcb);
770c2c66affSColin Finck
771c2c66affSColin Finck /* Read the number of runs while holding the MCB lock */
772c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
773c2c66affSColin Finck NumberOfRuns = FsRtlNumberOfRunsInBaseMcb(&(Mcb->BaseMcb));
774c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
775c2c66affSColin Finck
776c2c66affSColin Finck DPRINT("FsRtlNumberOfRunsInLargeMcb(%p) = %d\n", Mcb, NumberOfRuns);
777c2c66affSColin Finck
778c2c66affSColin Finck /* Return the count */
779c2c66affSColin Finck return NumberOfRuns;
780c2c66affSColin Finck }
781c2c66affSColin Finck
782c2c66affSColin Finck /*
783c2c66affSColin Finck * @implemented
784c2c66affSColin Finck * @Mcb: #PLARGE_MCB initialized by FsRtlInitializeLargeMcb().
785c2c66affSColin Finck * %NULL value is forbidden.
786c2c66affSColin Finck * @Vbn: Starting virtual block number to specify the range to delete.
787c2c66affSColin Finck * @SectorCount: Length of the range to delete.
788c2c66affSColin Finck * Value less or equal to %0 is forbidden; FIXME: Is the reject of %0 W32 compliant?
789c2c66affSColin Finck *
790c2c66affSColin Finck * Deletes any possible @Mcb mappings in the given range @Vbn ... @Vbn+@SectorCount-1.
791c2c66affSColin Finck * This call has no problems if no mappings exist there yet.
792c2c66affSColin Finck */
793c2c66affSColin Finck BOOLEAN
794c2c66affSColin Finck NTAPI
FsRtlRemoveBaseMcbEntry(IN PBASE_MCB OpaqueMcb,IN LONGLONG Vbn,IN LONGLONG SectorCount)795c2c66affSColin Finck FsRtlRemoveBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
796c2c66affSColin Finck IN LONGLONG Vbn,
797c2c66affSColin Finck IN LONGLONG SectorCount)
798c2c66affSColin Finck {
799c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
800c2c66affSColin Finck LARGE_MCB_MAPPING_ENTRY NeedleRun;
801c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY HaystackRun;
802c2c66affSColin Finck BOOLEAN Result = TRUE;
803c2c66affSColin Finck
804c2c66affSColin Finck DPRINT("FsRtlRemoveBaseMcbEntry(%p, %I64d, %I64d)\n", OpaqueMcb, Vbn, SectorCount);
805c2c66affSColin Finck
806c2c66affSColin Finck if (Vbn < 0 || SectorCount <= 0)
807c2c66affSColin Finck {
808c2c66affSColin Finck Result = FALSE;
809c2c66affSColin Finck goto quit;
810c2c66affSColin Finck }
811c2c66affSColin Finck
812c2c66affSColin Finck if (Vbn + SectorCount <= Vbn)
813c2c66affSColin Finck {
814c2c66affSColin Finck Result = FALSE;
815c2c66affSColin Finck goto quit;
816c2c66affSColin Finck }
817c2c66affSColin Finck
818c2c66affSColin Finck NeedleRun.RunStartVbn.QuadPart = Vbn;
819c2c66affSColin Finck NeedleRun.RunEndVbn.QuadPart = Vbn + SectorCount;
820*3d4cf8d2SJérôme Gardou NeedleRun.StartingLbn.QuadPart = -1;
821c2c66affSColin Finck
822c2c66affSColin Finck /* adjust/destroy all intersecting ranges */
823c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
824c2c66affSColin Finck while ((HaystackRun = RtlLookupElementGenericTable(&Mcb->Mapping->Table, &NeedleRun)))
825c2c66affSColin Finck {
826c2c66affSColin Finck if (HaystackRun->RunStartVbn.QuadPart < NeedleRun.RunStartVbn.QuadPart)
827c2c66affSColin Finck {
828*3d4cf8d2SJérôme Gardou LONGLONG HaystackRunEnd = HaystackRun->RunEndVbn.QuadPart;
829c2c66affSColin Finck ASSERT(HaystackRun->RunEndVbn.QuadPart > NeedleRun.RunStartVbn.QuadPart);
830*3d4cf8d2SJérôme Gardou
831c2c66affSColin Finck HaystackRun->RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart;
832*3d4cf8d2SJérôme Gardou
833*3d4cf8d2SJérôme Gardou if (HaystackRunEnd > NeedleRun.RunEndVbn.QuadPart)
834*3d4cf8d2SJérôme Gardou {
835*3d4cf8d2SJérôme Gardou /* The run we are deleting is included in the run we just truncated.
836*3d4cf8d2SJérôme Gardou * Add the tail back. */
837*3d4cf8d2SJérôme Gardou LARGE_MCB_MAPPING_ENTRY TailRun;
838*3d4cf8d2SJérôme Gardou BOOLEAN NewElement;
839*3d4cf8d2SJérôme Gardou
840*3d4cf8d2SJérôme Gardou TailRun.RunStartVbn.QuadPart = NeedleRun.RunEndVbn.QuadPart;
841*3d4cf8d2SJérôme Gardou TailRun.RunEndVbn.QuadPart = HaystackRunEnd;
842*3d4cf8d2SJérôme Gardou TailRun.StartingLbn.QuadPart = HaystackRun->StartingLbn.QuadPart + (NeedleRun.RunEndVbn.QuadPart - HaystackRun->RunStartVbn.QuadPart);
843*3d4cf8d2SJérôme Gardou
844*3d4cf8d2SJérôme Gardou Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
845*3d4cf8d2SJérôme Gardou
846*3d4cf8d2SJérôme Gardou RtlInsertElementGenericTable(&Mcb->Mapping->Table, &TailRun, sizeof(TailRun), &NewElement);
847*3d4cf8d2SJérôme Gardou ++Mcb->PairCount;
848*3d4cf8d2SJérôme Gardou ASSERT(NewElement);
849*3d4cf8d2SJérôme Gardou
850*3d4cf8d2SJérôme Gardou Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
851*3d4cf8d2SJérôme Gardou }
852c2c66affSColin Finck }
853c2c66affSColin Finck else if (HaystackRun->RunEndVbn.QuadPart > NeedleRun.RunEndVbn.QuadPart)
854c2c66affSColin Finck {
855*3d4cf8d2SJérôme Gardou LONGLONG HaystackRunStart = HaystackRun->RunStartVbn.QuadPart;
856*3d4cf8d2SJérôme Gardou LONGLONG HaystackStartingLbn = HaystackRun->StartingLbn.QuadPart;
857*3d4cf8d2SJérôme Gardou
858c2c66affSColin Finck ASSERT(HaystackRun->RunStartVbn.QuadPart < NeedleRun.RunEndVbn.QuadPart);
859c2c66affSColin Finck HaystackRun->RunStartVbn.QuadPart = NeedleRun.RunEndVbn.QuadPart;
860*3d4cf8d2SJérôme Gardou /* Adjust the starting LBN */
861*3d4cf8d2SJérôme Gardou HaystackRun->StartingLbn.QuadPart += NeedleRun.RunEndVbn.QuadPart - HaystackRunStart;
862*3d4cf8d2SJérôme Gardou
863*3d4cf8d2SJérôme Gardou if (HaystackRunStart < NeedleRun.RunStartVbn.QuadPart)
864*3d4cf8d2SJérôme Gardou {
865*3d4cf8d2SJérôme Gardou /* The run we are deleting is included in the run we just truncated.
866*3d4cf8d2SJérôme Gardou * Add the head back. */
867*3d4cf8d2SJérôme Gardou LARGE_MCB_MAPPING_ENTRY HeadRun;
868*3d4cf8d2SJérôme Gardou BOOLEAN NewElement;
869*3d4cf8d2SJérôme Gardou
870*3d4cf8d2SJérôme Gardou HeadRun.RunStartVbn.QuadPart = HaystackRunStart;
871*3d4cf8d2SJérôme Gardou HeadRun.RunEndVbn.QuadPart = NeedleRun.RunStartVbn.QuadPart;
872*3d4cf8d2SJérôme Gardou HeadRun.StartingLbn.QuadPart = HaystackStartingLbn;
873*3d4cf8d2SJérôme Gardou
874*3d4cf8d2SJérôme Gardou Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
875*3d4cf8d2SJérôme Gardou
876*3d4cf8d2SJérôme Gardou RtlInsertElementGenericTable(&Mcb->Mapping->Table, &HeadRun, sizeof(HeadRun), &NewElement);
877*3d4cf8d2SJérôme Gardou ++Mcb->PairCount;
878*3d4cf8d2SJérôme Gardou ASSERT(NewElement);
879*3d4cf8d2SJérôme Gardou
880*3d4cf8d2SJérôme Gardou Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
881*3d4cf8d2SJérôme Gardou }
882c2c66affSColin Finck }
883c2c66affSColin Finck else
884c2c66affSColin Finck {
885c2c66affSColin Finck //ASSERT(NeedleRun.RunStartVbn.QuadPart >= HaystackRun->RunStartVbn.QuadPart);
886c2c66affSColin Finck //ASSERT(NeedleRun.RunEndVbn.QuadPart <= HaystackRun->RunEndVbn.QuadPart);
887c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
888c2c66affSColin Finck RtlDeleteElementGenericTable(&Mcb->Mapping->Table, HaystackRun);
889c2c66affSColin Finck --Mcb->PairCount;
890c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingIntersectCompare;
891c2c66affSColin Finck }
892c2c66affSColin Finck }
893c2c66affSColin Finck Mcb->Mapping->Table.CompareRoutine = McbMappingCompare;
894c2c66affSColin Finck
895c2c66affSColin Finck quit:
896c2c66affSColin Finck DPRINT("FsRtlRemoveBaseMcbEntry(%p, %I64d, %I64d) = %d\n", OpaqueMcb, Vbn, SectorCount, Result);
897c2c66affSColin Finck return Result;
898c2c66affSColin Finck }
899c2c66affSColin Finck
900c2c66affSColin Finck /*
901c2c66affSColin Finck * @implemented
902c2c66affSColin Finck */
903c2c66affSColin Finck VOID
904c2c66affSColin Finck NTAPI
FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb,IN LONGLONG Vbn,IN LONGLONG SectorCount)905c2c66affSColin Finck FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb,
906c2c66affSColin Finck IN LONGLONG Vbn,
907c2c66affSColin Finck IN LONGLONG SectorCount)
908c2c66affSColin Finck {
909c2c66affSColin Finck DPRINT("FsRtlRemoveLargeMcbEntry(%p, %I64d, %I64d)\n", Mcb, Vbn, SectorCount);
910c2c66affSColin Finck
911c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
912c2c66affSColin Finck FsRtlRemoveBaseMcbEntry(&(Mcb->BaseMcb), Vbn, SectorCount);
913c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
914c2c66affSColin Finck }
915c2c66affSColin Finck
916c2c66affSColin Finck /*
917c2c66affSColin Finck * @implemented
918c2c66affSColin Finck */
919c2c66affSColin Finck VOID
920c2c66affSColin Finck NTAPI
FsRtlResetBaseMcb(IN PBASE_MCB OpaqueMcb)921c2c66affSColin Finck FsRtlResetBaseMcb(IN PBASE_MCB OpaqueMcb)
922c2c66affSColin Finck {
923c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
924c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY Element;
925c2c66affSColin Finck
926c2c66affSColin Finck DPRINT("FsRtlResetBaseMcb(%p)\n", OpaqueMcb);
927c2c66affSColin Finck
928c2c66affSColin Finck while (RtlNumberGenericTableElements(&Mcb->Mapping->Table) &&
929c2c66affSColin Finck (Element = (PLARGE_MCB_MAPPING_ENTRY)RtlGetElementGenericTable(&Mcb->Mapping->Table, 0)))
930c2c66affSColin Finck {
931c2c66affSColin Finck RtlDeleteElementGenericTable(&Mcb->Mapping->Table, Element);
932c2c66affSColin Finck }
933c2c66affSColin Finck
934c2c66affSColin Finck Mcb->PairCount = 0;
935c2c66affSColin Finck Mcb->MaximumPairCount = 0;
936c2c66affSColin Finck }
937c2c66affSColin Finck
938c2c66affSColin Finck /*
939c2c66affSColin Finck * @implemented
940c2c66affSColin Finck */
941c2c66affSColin Finck VOID
942c2c66affSColin Finck NTAPI
FsRtlResetLargeMcb(IN PLARGE_MCB Mcb,IN BOOLEAN SelfSynchronized)943c2c66affSColin Finck FsRtlResetLargeMcb(IN PLARGE_MCB Mcb,
944c2c66affSColin Finck IN BOOLEAN SelfSynchronized)
945c2c66affSColin Finck {
946c2c66affSColin Finck DPRINT("FsRtlResetLargeMcb(%p, %d)\n", Mcb, SelfSynchronized);
947c2c66affSColin Finck
948c2c66affSColin Finck if (!SelfSynchronized)
949c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
950c2c66affSColin Finck
951c2c66affSColin Finck FsRtlResetBaseMcb(&Mcb->BaseMcb);
952c2c66affSColin Finck
953c2c66affSColin Finck if (!SelfSynchronized)
954c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
955c2c66affSColin Finck }
956c2c66affSColin Finck
957c2c66affSColin Finck /*
958c2c66affSColin Finck * @unimplemented
959c2c66affSColin Finck */
960c2c66affSColin Finck BOOLEAN
961c2c66affSColin Finck NTAPI
FsRtlSplitBaseMcb(IN PBASE_MCB OpaqueMcb,IN LONGLONG Vbn,IN LONGLONG Amount)962c2c66affSColin Finck FsRtlSplitBaseMcb(IN PBASE_MCB OpaqueMcb,
963c2c66affSColin Finck IN LONGLONG Vbn,
964c2c66affSColin Finck IN LONGLONG Amount)
965c2c66affSColin Finck {
966c2c66affSColin Finck PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
967c2c66affSColin Finck PLARGE_MCB_MAPPING_ENTRY Run, InsertLowerRun = NULL, ExistingRun = NULL;
968c2c66affSColin Finck BOOLEAN NewElement;
969c2c66affSColin Finck
970c2c66affSColin Finck DPRINT("FsRtlSplitBaseMcb(%p, %I64d, %I64d)\n", OpaqueMcb, Vbn, Amount);
971c2c66affSColin Finck
972c2c66affSColin Finck /* Traverse the tree */
973c2c66affSColin Finck for (Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
974c2c66affSColin Finck Run;
975c2c66affSColin Finck Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
976c2c66affSColin Finck {
977c2c66affSColin Finck /* unaffected run? */
978c2c66affSColin Finck /* FIXME: performance: effective skip of all 'lower' runs without traversing them */
979c2c66affSColin Finck if (Vbn >= Run->RunEndVbn.QuadPart) { DPRINT("Skipping it\n"); continue; }
980c2c66affSColin Finck
981c2c66affSColin Finck /* crossing run to be split?
982c2c66affSColin Finck * 'lower_run' is created on the original place; just shortened.
983c2c66affSColin Finck * current 'run' is shifted up later
984c2c66affSColin Finck */
985c2c66affSColin Finck if (Vbn < Run->RunEndVbn.QuadPart)
986c2c66affSColin Finck {
987c2c66affSColin Finck /* FIXME: shift 'run->Lbn_start' ? */
988c2c66affSColin Finck Run->RunStartVbn.QuadPart = Vbn;
989c2c66affSColin Finck
990c2c66affSColin Finck InsertLowerRun = NULL;
991c2c66affSColin Finck }
992c2c66affSColin Finck
993c2c66affSColin Finck /* Shift the current 'run'.
994c2c66affSColin Finck * Ordering is not changed in Generic Tree so I hope I do not need to reinsert it.
995c2c66affSColin Finck */
996c2c66affSColin Finck Run->RunStartVbn.QuadPart += Amount;
997c2c66affSColin Finck ASSERT(Run->RunEndVbn.QuadPart + Amount > Run->RunEndVbn.QuadPart); /* overflow? */
998c2c66affSColin Finck Run->RunEndVbn.QuadPart += Amount;
999c2c66affSColin Finck /* FIXME: shift 'run->Lbn_start' ? */
1000c2c66affSColin Finck
1001c2c66affSColin Finck /* continue the traversal */
1002c2c66affSColin Finck }
1003c2c66affSColin Finck
1004c2c66affSColin Finck if (InsertLowerRun)
1005c2c66affSColin Finck {
1006c2c66affSColin Finck ExistingRun = RtlInsertElementGenericTable(&Mcb->Mapping->Table, InsertLowerRun, sizeof(*InsertLowerRun), &NewElement);
1007c2c66affSColin Finck ++Mcb->PairCount;
1008c2c66affSColin Finck }
1009c2c66affSColin Finck
1010c2c66affSColin Finck ASSERT(ExistingRun == NULL);
1011c2c66affSColin Finck
1012c2c66affSColin Finck DPRINT("FsRtlSplitBaseMcb(%p, %I64d, %I64d) = %d\n", OpaqueMcb, Vbn, Amount, TRUE);
1013c2c66affSColin Finck
1014c2c66affSColin Finck return TRUE;
1015c2c66affSColin Finck }
1016c2c66affSColin Finck
1017c2c66affSColin Finck /*
1018c2c66affSColin Finck * @implemented
1019c2c66affSColin Finck */
1020c2c66affSColin Finck BOOLEAN
1021c2c66affSColin Finck NTAPI
FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb,IN LONGLONG Vbn,IN LONGLONG Amount)1022c2c66affSColin Finck FsRtlSplitLargeMcb(IN PLARGE_MCB Mcb,
1023c2c66affSColin Finck IN LONGLONG Vbn,
1024c2c66affSColin Finck IN LONGLONG Amount)
1025c2c66affSColin Finck {
1026c2c66affSColin Finck BOOLEAN Result;
1027c2c66affSColin Finck
1028c2c66affSColin Finck DPRINT("FsRtlSplitLargeMcb(%p, %I64d, %I64d)\n", Mcb, Vbn, Amount);
1029c2c66affSColin Finck
1030c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
1031c2c66affSColin Finck Result = FsRtlSplitBaseMcb(&(Mcb->BaseMcb),
1032c2c66affSColin Finck Vbn,
1033c2c66affSColin Finck Amount);
1034c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
1035c2c66affSColin Finck
1036c2c66affSColin Finck DPRINT("FsRtlSplitLargeMcb(%p, %I64d, %I64d) = %d\n", Mcb, Vbn, Amount, Result);
1037c2c66affSColin Finck
1038c2c66affSColin Finck return Result;
1039c2c66affSColin Finck }
1040c2c66affSColin Finck
1041c2c66affSColin Finck /*
1042c2c66affSColin Finck * @unimplemented
1043c2c66affSColin Finck */
1044c2c66affSColin Finck VOID
1045c2c66affSColin Finck NTAPI
FsRtlTruncateBaseMcb(IN PBASE_MCB OpaqueMcb,IN LONGLONG Vbn)1046c2c66affSColin Finck FsRtlTruncateBaseMcb(IN PBASE_MCB OpaqueMcb,
1047c2c66affSColin Finck IN LONGLONG Vbn)
1048c2c66affSColin Finck {
1049c2c66affSColin Finck DPRINT("FsRtlTruncateBaseMcb(%p, %I64d)\n", OpaqueMcb, Vbn);
1050c2c66affSColin Finck
1051c2c66affSColin Finck FsRtlRemoveBaseMcbEntry(OpaqueMcb, Vbn, MAXLONG - Vbn + 1);
1052c2c66affSColin Finck }
1053c2c66affSColin Finck
1054c2c66affSColin Finck /*
1055c2c66affSColin Finck * @implemented
1056c2c66affSColin Finck */
1057c2c66affSColin Finck VOID
1058c2c66affSColin Finck NTAPI
FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb,IN LONGLONG Vbn)1059c2c66affSColin Finck FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb,
1060c2c66affSColin Finck IN LONGLONG Vbn)
1061c2c66affSColin Finck {
1062c2c66affSColin Finck DPRINT("FsRtlTruncateLargeMcb(%p, %I64d)\n", Mcb, Vbn);
1063c2c66affSColin Finck
1064c2c66affSColin Finck KeAcquireGuardedMutex(Mcb->GuardedMutex);
1065c2c66affSColin Finck FsRtlTruncateBaseMcb(&(Mcb->BaseMcb), Vbn);
1066c2c66affSColin Finck KeReleaseGuardedMutex(Mcb->GuardedMutex);
1067c2c66affSColin Finck }
1068c2c66affSColin Finck
1069c2c66affSColin Finck /*
1070c2c66affSColin Finck * @implemented
1071c2c66affSColin Finck */
1072c2c66affSColin Finck VOID
1073c2c66affSColin Finck NTAPI
FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb)1074c2c66affSColin Finck FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb)
1075c2c66affSColin Finck {
1076c2c66affSColin Finck DPRINT("FsRtlUninitializeBaseMcb(%p)\n", Mcb);
1077c2c66affSColin Finck
1078c2c66affSColin Finck FsRtlResetBaseMcb(Mcb);
1079c2c66affSColin Finck
1080c2c66affSColin Finck if ((Mcb->PoolType == PagedPool)/* && (Mcb->MaximumPairCount == MAXIMUM_PAIR_COUNT)*/)
1081c2c66affSColin Finck {
1082c2c66affSColin Finck ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList,
1083c2c66affSColin Finck Mcb->Mapping);
1084c2c66affSColin Finck }
1085c2c66affSColin Finck else
1086c2c66affSColin Finck {
10873b2f1585SHermès Bélusca-Maïto ExFreePoolWithTag(Mcb->Mapping, 'CBSF');
1088c2c66affSColin Finck }
1089c2c66affSColin Finck }
1090c2c66affSColin Finck
1091c2c66affSColin Finck /*
1092c2c66affSColin Finck * @implemented
1093c2c66affSColin Finck */
1094c2c66affSColin Finck VOID
1095c2c66affSColin Finck NTAPI
FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)1096c2c66affSColin Finck FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)
1097c2c66affSColin Finck {
1098c2c66affSColin Finck DPRINT("FsRtlUninitializeLargeMcb(%p)\n", Mcb);
1099c2c66affSColin Finck
1100c2c66affSColin Finck if (Mcb->GuardedMutex)
1101c2c66affSColin Finck {
1102c2c66affSColin Finck ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList,
1103c2c66affSColin Finck Mcb->GuardedMutex);
1104c2c66affSColin Finck FsRtlUninitializeBaseMcb(&(Mcb->BaseMcb));
1105c2c66affSColin Finck }
1106c2c66affSColin Finck }
1107