mirror of
https://github.com/reactos/reactos.git
synced 2025-05-25 20:18:22 +00:00
[NTOSKRNL]
Cherry pick r71407 by Trevor Thompson: - Rewrote FsRtlGetNextBaseMcbEntry(), FsRtlLookupBaseMcbEntry(), and FsRtlNumberOfRunsInBaseMcb() using simpler logic. This finally fixes broken MCB handling in ReactOS and allows FSDs relying on MCB to properly work in ReactOS! CORE-11002 #resolve #comment Fixed in r71409 svn path=/trunk/; revision=71409
This commit is contained in:
parent
a5a8ffb511
commit
e6b12e4774
1 changed files with 77 additions and 190 deletions
|
@ -5,6 +5,7 @@
|
||||||
* PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers
|
* PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers
|
||||||
* PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
|
* PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
|
||||||
* Jan Kratochvil <project-captive@jankratochvil.net>
|
* Jan Kratochvil <project-captive@jankratochvil.net>
|
||||||
|
* Trevor Thompson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -42,11 +43,13 @@ typedef struct _BASE_MCB_INTERNAL {
|
||||||
PLARGE_MCB_MAPPING Mapping;
|
PLARGE_MCB_MAPPING Mapping;
|
||||||
} BASE_MCB_INTERNAL, *PBASE_MCB_INTERNAL;
|
} BASE_MCB_INTERNAL, *PBASE_MCB_INTERNAL;
|
||||||
|
|
||||||
|
/*
|
||||||
static LARGE_MCB_MAPPING_ENTRY StaticRunBelow0 = {
|
static LARGE_MCB_MAPPING_ENTRY StaticRunBelow0 = {
|
||||||
{{-1}}, /* ignored */
|
{{-1}}, // ignored
|
||||||
{{0}},
|
{{0}},
|
||||||
{{-1}}, /* ignored */
|
{{-1}}, // ignored
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
static PVOID NTAPI McbMappingAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
|
static PVOID NTAPI McbMappingAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
|
||||||
{
|
{
|
||||||
|
@ -321,103 +324,59 @@ FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb,
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
|
FsRtlGetNextBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
|
||||||
IN ULONG RunIndex,
|
IN ULONG RunIndex,
|
||||||
OUT PLONGLONG Vbn,
|
OUT PLONGLONG Vbn,
|
||||||
OUT PLONGLONG Lbn,
|
OUT PLONGLONG Lbn,
|
||||||
OUT PLONGLONG SectorCount)
|
OUT PLONGLONG SectorCount)
|
||||||
{
|
{
|
||||||
BOOLEAN Result = FALSE;
|
BOOLEAN Result = FALSE;
|
||||||
PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
|
PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
|
||||||
ULONG RunIndexRemaining;
|
PLARGE_MCB_MAPPING_ENTRY Run = NULL;
|
||||||
PLARGE_MCB_MAPPING_ENTRY Run, RunFound = NULL, RunFoundLower = NULL, RunFoundHigher = NULL;
|
ULONG CurrentIndex = 0;
|
||||||
BOOLEAN First = TRUE;
|
ULONGLONG LastVbn = 0;
|
||||||
|
ULONGLONG LastSectorCount = 0;
|
||||||
|
|
||||||
DPRINT("FsRtlGetNextBaseMcbEntry(%p, %d, %p, %p, %p)\n", OpaqueMcb, RunIndex, Vbn, Lbn, SectorCount);
|
// Traverse the tree
|
||||||
|
|
||||||
RunIndexRemaining = RunIndex;
|
|
||||||
|
|
||||||
/* Traverse the tree */
|
|
||||||
for (Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
|
for (Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
|
||||||
Run;
|
Run;
|
||||||
Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
|
Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
|
||||||
{
|
{
|
||||||
if (First)
|
// is the current index a hole?
|
||||||
|
if (Run->RunStartVbn.QuadPart > (LastVbn + LastSectorCount))
|
||||||
{
|
{
|
||||||
/* Take care when we must emulate missing 'hole' run at start of our run list. */
|
// Is this the index we're looking for?
|
||||||
if (Run->RunStartVbn.QuadPart > 0)
|
if (RunIndex == CurrentIndex)
|
||||||
{
|
{
|
||||||
if (RunIndexRemaining == 0)
|
*Vbn = LastVbn + LastSectorCount;
|
||||||
{
|
*Lbn = -1;
|
||||||
RunFoundLower = &StaticRunBelow0;
|
*SectorCount = Run->RunStartVbn.QuadPart - *Vbn;
|
||||||
RunFoundHigher = Run;
|
|
||||||
|
|
||||||
/* stop the traversal */
|
Result = TRUE;
|
||||||
break;
|
goto quit;
|
||||||
}
|
|
||||||
/* If someone wants RunIndex #1 we are already on it. */
|
|
||||||
RunIndexRemaining--;
|
|
||||||
}
|
}
|
||||||
First = FALSE;
|
|
||||||
|
CurrentIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RunIndexRemaining > 0)
|
if (RunIndex == CurrentIndex)
|
||||||
{
|
{
|
||||||
/* FIXME: performance: non-linear direct seek to the requested RunIndex */
|
*Vbn = Run->RunStartVbn.QuadPart;
|
||||||
RunIndexRemaining--;
|
*Lbn = Run->StartingLbn.QuadPart;
|
||||||
if (RunIndexRemaining == 0)
|
*SectorCount = Run->RunEndVbn.QuadPart - Run->RunStartVbn.QuadPart;
|
||||||
RunFoundLower = Run;
|
|
||||||
else
|
|
||||||
RunIndexRemaining--;
|
|
||||||
|
|
||||||
/* continue the traversal */
|
Result = TRUE;
|
||||||
continue;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RunFoundLower)
|
CurrentIndex++;
|
||||||
RunFoundHigher = Run;
|
LastVbn = Run->RunStartVbn.QuadPart;
|
||||||
else
|
LastSectorCount = Run->RunEndVbn.QuadPart - Run->RunStartVbn.QuadPart;
|
||||||
RunFound = Run;
|
|
||||||
|
|
||||||
/* stop the traversal */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RunFound) DPRINT("RunFound(%lu %lu %lu)\n", RunFound->RunStartVbn.LowPart, RunFound->RunEndVbn.LowPart, RunFound->StartingLbn.LowPart);
|
// these values are meaningless when returning false (but setting them can be helpful for debugging purposes)
|
||||||
if (RunFoundLower) DPRINT("RunFoundLower(%lu %lu %lu)\n", RunFoundLower->RunStartVbn.LowPart, RunFoundLower->RunEndVbn.LowPart, RunFoundLower->StartingLbn.LowPart);
|
*Vbn = 0xdeadbeef;
|
||||||
if (RunFoundHigher) DPRINT("RunFoundHigher(%lu %lu %lu)\n", RunFoundHigher->RunStartVbn.LowPart, RunFoundHigher->RunEndVbn.LowPart, RunFoundHigher->StartingLbn.LowPart);
|
*Lbn = 0xdeadbeef;
|
||||||
|
*SectorCount = 0xdeadbeef;
|
||||||
if (RunFound)
|
|
||||||
{
|
|
||||||
ASSERT(RunFoundLower == NULL);
|
|
||||||
ASSERT(RunFoundHigher == NULL);
|
|
||||||
|
|
||||||
if (Vbn)
|
|
||||||
*Vbn = RunFound->RunStartVbn.QuadPart;
|
|
||||||
if (Lbn)
|
|
||||||
*Lbn = RunFound->StartingLbn.QuadPart;
|
|
||||||
if (SectorCount)
|
|
||||||
*SectorCount = RunFound->RunEndVbn.QuadPart - RunFound->RunStartVbn.QuadPart;
|
|
||||||
|
|
||||||
Result = TRUE;
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RunFoundLower && RunFoundHigher)
|
|
||||||
{
|
|
||||||
//ASSERT(RunFoundHigher != NULL);
|
|
||||||
|
|
||||||
if (Vbn)
|
|
||||||
*Vbn = RunFoundLower->RunEndVbn.QuadPart;
|
|
||||||
if (Lbn)
|
|
||||||
*Lbn = -1;
|
|
||||||
if (SectorCount)
|
|
||||||
*SectorCount = RunFoundHigher->RunStartVbn.QuadPart - RunFoundLower->RunEndVbn.QuadPart;
|
|
||||||
|
|
||||||
Result = TRUE;
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(RunFoundHigher == NULL);
|
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
DPRINT("FsRtlGetNextBaseMcbEntry(%p, %d, %p, %p, %p) = %d (%I64d, %I64d, %I64d)\n", Mcb, RunIndex, Vbn, Lbn, SectorCount, Result, *Vbn, *Lbn, *SectorCount);
|
DPRINT("FsRtlGetNextBaseMcbEntry(%p, %d, %p, %p, %p) = %d (%I64d, %I64d, %I64d)\n", Mcb, RunIndex, Vbn, Lbn, SectorCount, Result, *Vbn, *Lbn, *SectorCount);
|
||||||
|
@ -538,117 +497,55 @@ FsRtlInitializeLargeMcbs(VOID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
FsRtlLookupBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
|
FsRtlLookupBaseMcbEntry(IN PBASE_MCB OpaqueMcb,
|
||||||
IN LONGLONG Vbn,
|
IN LONGLONG Vbn,
|
||||||
OUT PLONGLONG Lbn OPTIONAL,
|
OUT PLONGLONG Lbn OPTIONAL,
|
||||||
OUT PLONGLONG SectorCountFromLbn OPTIONAL,
|
OUT PLONGLONG SectorCountFromLbn OPTIONAL,
|
||||||
OUT PLONGLONG StartingLbn OPTIONAL,
|
OUT PLONGLONG StartingLbn OPTIONAL,
|
||||||
OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,
|
OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL,
|
||||||
OUT PULONG Index OPTIONAL)
|
OUT PULONG Index OPTIONAL)
|
||||||
{
|
{
|
||||||
BOOLEAN Result = FALSE;
|
BOOLEAN Result = FALSE;
|
||||||
PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
|
ULONG i;
|
||||||
|
LONGLONG LastVbn = 0, LastLbn = 0, Count = 0; // the last values we've found during traversal
|
||||||
ULONG RunIndex = 0;
|
|
||||||
PLARGE_MCB_MAPPING_ENTRY Run, RunFound = NULL, RunFoundLower = NULL, RunFoundHigher = NULL;
|
|
||||||
BOOLEAN First = TRUE;
|
|
||||||
|
|
||||||
DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p)\n", OpaqueMcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, SectorCountFromStartingLbn, Index);
|
DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p)\n", OpaqueMcb, Vbn, Lbn, SectorCountFromLbn, StartingLbn, SectorCountFromStartingLbn, Index);
|
||||||
|
|
||||||
/* Traverse the tree */
|
for (i = 0; FsRtlGetNextBaseMcbEntry(OpaqueMcb, i, &LastVbn, &LastLbn, &Count); i++)
|
||||||
for (Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, TRUE);
|
|
||||||
Run;
|
|
||||||
Run = (PLARGE_MCB_MAPPING_ENTRY)RtlEnumerateGenericTable(&Mcb->Mapping->Table, FALSE))
|
|
||||||
{
|
{
|
||||||
if (First)
|
// have we reached the target mapping?
|
||||||
|
if (Vbn < LastVbn + Count)
|
||||||
{
|
{
|
||||||
/* Take care when we must emulate missing 'hole' run at start of our run list. */
|
if (Lbn)
|
||||||
if (Run->RunStartVbn.QuadPart > 0)
|
|
||||||
{
|
{
|
||||||
RunIndex++;
|
if (LastLbn == -1)
|
||||||
RunFoundLower = &StaticRunBelow0;
|
*Lbn = -1;
|
||||||
|
else
|
||||||
|
*Lbn = LastLbn + (Vbn - LastVbn);
|
||||||
}
|
}
|
||||||
First = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Run->RunStartVbn.QuadPart <= Vbn && Vbn < Run->RunEndVbn.QuadPart)
|
if (SectorCountFromLbn)
|
||||||
{
|
*SectorCountFromLbn = LastVbn + Count - Vbn;
|
||||||
RunFound = Run;
|
if (StartingLbn)
|
||||||
RunFoundLower = NULL;
|
*StartingLbn = LastLbn;
|
||||||
/* stop the traversal; hit */
|
if (SectorCountFromStartingLbn)
|
||||||
break;
|
*SectorCountFromStartingLbn = LastVbn + Count - LastVbn;
|
||||||
}
|
if (Index)
|
||||||
|
*Index = i;
|
||||||
|
|
||||||
if (Run->RunEndVbn.QuadPart <= Vbn)
|
Result = TRUE;
|
||||||
{
|
goto quit;
|
||||||
RunFoundLower = Run;
|
|
||||||
if (Run->StartingLbn.QuadPart > 0)
|
|
||||||
{
|
|
||||||
RunIndex += 2;
|
|
||||||
}
|
|
||||||
/* continue the traversal; not yet crossed by the run */
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vbn < Run->RunStartVbn.QuadPart)
|
|
||||||
{
|
|
||||||
RunFoundHigher = Run;
|
|
||||||
RunIndex++;
|
|
||||||
/* stop the traversal; the run skipped us */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(FALSE);
|
|
||||||
/* stop the traversal */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RunFound)
|
if (Lbn)
|
||||||
{
|
*Lbn = -1;
|
||||||
ASSERT(RunFoundLower == NULL);
|
if (StartingLbn)
|
||||||
ASSERT(RunFoundHigher == NULL);
|
*StartingLbn = -1;
|
||||||
|
|
||||||
if (Lbn)
|
|
||||||
*Lbn = RunFound->StartingLbn.QuadPart + (Vbn - RunFound->RunStartVbn.QuadPart);
|
|
||||||
|
|
||||||
if (SectorCountFromLbn) /* FIXME: 'after' means including current 'Lbn' or without it? */
|
|
||||||
*SectorCountFromLbn = RunFound->RunEndVbn.QuadPart - Vbn;
|
|
||||||
if (StartingLbn)
|
|
||||||
*StartingLbn = RunFound->StartingLbn.QuadPart;
|
|
||||||
if (SectorCountFromStartingLbn)
|
|
||||||
*SectorCountFromStartingLbn = RunFound->RunEndVbn.QuadPart - RunFound->RunStartVbn.QuadPart;
|
|
||||||
if (Index)
|
|
||||||
*Index = RunIndex;
|
|
||||||
|
|
||||||
Result = TRUE;
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RunFoundHigher)
|
|
||||||
{
|
|
||||||
/* search for hole */
|
|
||||||
ASSERT(RunFoundLower != NULL);
|
|
||||||
|
|
||||||
if (Lbn)
|
|
||||||
*Lbn = ~0ull;
|
|
||||||
if (SectorCountFromLbn) /* FIXME: 'after' means including current 'Lbn' or without it? */
|
|
||||||
*SectorCountFromLbn = RunFoundHigher->RunStartVbn.QuadPart - Vbn;
|
|
||||||
if (StartingLbn)
|
|
||||||
*StartingLbn = ~0ull;
|
|
||||||
if (SectorCountFromStartingLbn)
|
|
||||||
*SectorCountFromStartingLbn = RunFoundHigher->RunStartVbn.QuadPart - RunFoundLower->RunEndVbn.QuadPart;
|
|
||||||
if (Index)
|
|
||||||
*Index = RunIndex - 2;
|
|
||||||
|
|
||||||
Result = TRUE;
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We may have some 'RunFoundLower'. */
|
|
||||||
|
|
||||||
quit:
|
quit:
|
||||||
DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p) = %d (%I64d, %I64d, %I64d, %I64d, %d)\n",
|
DPRINT("FsRtlLookupBaseMcbEntry(%p, %I64d, %p, %p, %p, %p, %p) = %d (%I64d, %I64d, %I64d, %I64d, %d)\n",
|
||||||
|
@ -848,28 +745,18 @@ ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb)
|
FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB OpaqueMcb)
|
||||||
{
|
{
|
||||||
PBASE_MCB_INTERNAL Mcb = (PBASE_MCB_INTERNAL)OpaqueMcb;
|
|
||||||
LONGLONG LbnAtVbn0 = -1;
|
|
||||||
ULONG NumberOfRuns = 0;
|
ULONG NumberOfRuns = 0;
|
||||||
|
LONGLONG Vbn, Lbn, Count;
|
||||||
|
int i;
|
||||||
|
|
||||||
DPRINT("FsRtlNumberOfRunsInBaseMcb(%p)\n", OpaqueMcb);
|
DPRINT("FsRtlNumberOfRunsInBaseMcb(%p)\n", OpaqueMcb);
|
||||||
|
|
||||||
if (Mcb->PairCount == 0) goto quit;
|
// Count how many Mcb entries there are
|
||||||
|
for (i = 0; FsRtlGetNextBaseMcbEntry(OpaqueMcb, i, &Vbn, &Lbn, &Count); i++)
|
||||||
|
{
|
||||||
|
NumberOfRuns++;
|
||||||
|
}
|
||||||
|
|
||||||
FsRtlLookupBaseMcbEntry(OpaqueMcb,
|
|
||||||
0, /* Vbn */
|
|
||||||
&LbnAtVbn0, /* Lbn */
|
|
||||||
NULL, NULL, NULL, NULL); /* 4 output arguments - not interested in them */
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the count */
|
|
||||||
//return Mcb->PairCount;
|
|
||||||
/* Return the number of 'real' and 'hole' runs.
|
|
||||||
* If we do not have sector 0 as 'real' emulate a 'hole' there.
|
|
||||||
*/
|
|
||||||
NumberOfRuns = Mcb->PairCount * 2 - (LbnAtVbn0 != -1 ? 1 : 0); /* include holes as runs */
|
|
||||||
|
|
||||||
quit:
|
|
||||||
DPRINT("FsRtlNumberOfRunsInBaseMcb(%p) = %d\n", OpaqueMcb, NumberOfRuns);
|
DPRINT("FsRtlNumberOfRunsInBaseMcb(%p) = %d\n", OpaqueMcb, NumberOfRuns);
|
||||||
return NumberOfRuns;
|
return NumberOfRuns;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue