Author: arty Date: Wed Feb 29 09:18:01 2012 New Revision: 55914
URL: http://svn.reactos.org/svn/reactos?rev=55914&view=rev Log: [FSRTL] Import code from Pierre Schweitzer's fsrtl branch. - Large MCB and MCB - Change notification
Added: trunk/reactos/ntoskrnl/fsrtl/mcb.c (with props) Modified: trunk/reactos/ntoskrnl/CMakeLists.txt trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c trunk/reactos/ntoskrnl/fsrtl/largemcb.c trunk/reactos/ntoskrnl/fsrtl/notify.c trunk/reactos/ntoskrnl/include/internal/fsrtl.h
Modified: trunk/reactos/ntoskrnl/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/CMakeLists.txt?rev... ============================================================================== --- trunk/reactos/ntoskrnl/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/CMakeLists.txt [iso-8859-1] Wed Feb 29 09:18:01 2012 @@ -119,6 +119,7 @@ fsrtl/fsfilter.c fsrtl/fsrtlpc.c fsrtl/largemcb.c + fsrtl/mcb.c fsrtl/name.c fsrtl/notify.c fsrtl/oplock.c
Modified: trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/fsrtl/fsrtlpc.c [iso-8859-1] Wed Feb 29 09:18:01 2012 @@ -169,6 +169,8 @@ IFS_POOL_TAG, 0);
+ FsRtlInitializeLargeMcbs(); + /* Allocate the Resource Buffer */ FsRtlPagingIoResources = FsRtlAllocatePoolWithTag(NonPagedPool, FSRTL_MAX_RESOURCES *
Modified: trunk/reactos/ntoskrnl/fsrtl/largemcb.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/largemcb.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] Wed Feb 29 09:18:01 2012 @@ -2,20 +2,138 @@ * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/fsrtl/largemcb.c - * PURPOSE: Mapping Control Block (MCB) support for File System Drivers + * PURPOSE: Large Mapped Control Block (MCB) support for File System Drivers * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Pierre Schweitzer (heis_spiter@hotmail.com) + * Art Yerkes (art.yerkes@gmail.com) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h> -#define NDEBUG +//#define NDEBUG #include <debug.h>
+/* GLOBALS *******************************************************************/ + +#define GET_LIST_HEAD(x) ((PLIST_ENTRY)(&((PRTL_GENERIC_TABLE)x)[1])) + +PAGED_LOOKASIDE_LIST FsRtlFirstMappingLookasideList; +NPAGED_LOOKASIDE_LIST FsRtlFastMutexLookasideList; + +typedef struct _LARGE_MCB_MAPPING_ENTRY +{ + LARGE_INTEGER RunStartVbn; + LARGE_INTEGER SectorCount; + LARGE_INTEGER StartingLbn; + LIST_ENTRY Sequence; +} LARGE_MCB_MAPPING_ENTRY, *PLARGE_MCB_MAPPING_ENTRY; + +static PVOID NTAPI McbMappingAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes) +{ + PVOID Result; + PBASE_MCB Mcb = (PBASE_MCB)Table->TableContext; + Result = ExAllocatePoolWithTag(Mcb->PoolType, Bytes, 'LMCB'); + DPRINT("McbMappingAllocate(%d) => %p\n", Bytes, Result); + return Result; +} + +static VOID NTAPI McbMappingFree(PRTL_GENERIC_TABLE Table, PVOID Buffer) +{ + DPRINT("McbMappingFree(%p)\n", Buffer); + ExFreePoolWithTag(Buffer, 'LMCB'); +} + +static RTL_GENERIC_COMPARE_RESULTS NTAPI McbMappingCompare +(RTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB) +{ + PLARGE_MCB_MAPPING_ENTRY A = PtrA, B = PtrB; + return + (A->RunStartVbn.QuadPart + A->SectorCount.QuadPart < + B->RunStartVbn.QuadPart) ? GenericLessThan : + (A->RunStartVbn.QuadPart > + B->RunStartVbn.QuadPart + B->SectorCount.QuadPart) ? + GenericGreaterThan : GenericEqual; +} + /* PUBLIC FUNCTIONS **********************************************************/
/* - * @unimplemented + * @implemented + */ +BOOLEAN +NTAPI +FsRtlAddBaseMcbEntry(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Lbn, + IN LONGLONG SectorCount) +{ + LARGE_MCB_MAPPING_ENTRY Node; + PLARGE_MCB_MAPPING_ENTRY Existing = NULL; + BOOLEAN NewElement = FALSE; + + Node.RunStartVbn.QuadPart = Vbn; + Node.StartingLbn.QuadPart = Lbn; + Node.SectorCount.QuadPart = SectorCount; + + while (!NewElement) + { + DPRINT("Inserting %x:%x\n", Node.RunStartVbn.LowPart, Node.SectorCount.LowPart); + Existing = RtlInsertElementGenericTable + (Mcb->Mapping, &Node, sizeof(Node), &NewElement); + DPRINT("Existing %x\n", Existing); + if (!Existing) break; + + DPRINT("NewElement %d\n", NewElement); + if (!NewElement) + { + // We merge the existing runs + LARGE_INTEGER StartVbn, FinalVbn; + DPRINT("Existing: %x:%x\n", + Existing->RunStartVbn.LowPart, Node.SectorCount.LowPart); + if (Existing->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) + { + StartVbn = Existing->RunStartVbn; + Node.StartingLbn = Existing->StartingLbn; + } + else + { + StartVbn = Node.RunStartVbn; + } + DPRINT("StartVbn %x\n", StartVbn.LowPart); + if (Existing->RunStartVbn.QuadPart + Existing->SectorCount.QuadPart > + Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart) + { + FinalVbn.QuadPart = + Existing->RunStartVbn.QuadPart + Existing->SectorCount.QuadPart; + } + else + { + FinalVbn.QuadPart = + Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart; + } + DPRINT("FinalVbn %x\n", FinalVbn.LowPart); + Node.RunStartVbn.QuadPart = StartVbn.QuadPart; + Node.SectorCount.QuadPart = FinalVbn.QuadPart - StartVbn.QuadPart; + RemoveHeadList(&Existing->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Existing); + Mcb->PairCount--; + } + else + { + DPRINT("Mapping added %x\n", Existing); + Mcb->MaximumPairCount++; + Mcb->PairCount++; + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Existing->Sequence); + } + } + + DPRINT("!!Existing %d\n", !!Existing); + return !!Existing; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -24,30 +142,57 @@ IN LONGLONG Lbn, IN LONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); - return FALSE; -} - -/* - * @implemented - */ -BOOLEAN -NTAPI -FsRtlAddMcbEntry(IN PMCB Mcb, - IN VBN Vbn, - IN LBN Lbn, - IN ULONG SectorCount) -{ - /* Call the newer function */ - return FsRtlAddLargeMcbEntry(&Mcb-> - DummyFieldThatSizesThisStructureCorrectly, - (LONGLONG)Vbn, - (LONGLONG)Lbn, - (LONGLONG)SectorCount); + BOOLEAN Result; + + DPRINT("Mcb %x Vbn %x Lbn %x SectorCount %x\n", Mcb, Vbn, Lbn, SectorCount); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlAddBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + Lbn, + SectorCount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; }
/* * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlGetNextBaseMcbEntry(IN PBASE_MCB Mcb, + IN ULONG RunIndex, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn, + OUT PLONGLONG SectorCount) +{ + ULONG i = 0; + BOOLEAN Result = FALSE; + PLARGE_MCB_MAPPING_ENTRY Entry; + for (Entry = (PLARGE_MCB_MAPPING_ENTRY) + RtlEnumerateGenericTable(Mcb->Mapping, TRUE); + Entry && i < RunIndex; + Entry = (PLARGE_MCB_MAPPING_ENTRY) + RtlEnumerateGenericTable(Mcb->Mapping, FALSE), i++); + if (Entry) + { + Result = TRUE; + if (Vbn) + *Vbn = Entry->RunStartVbn.QuadPart; + if (Lbn) + *Lbn = Entry->StartingLbn.QuadPart; + if (SectorCount) + *SectorCount = Entry->SectorCount.QuadPart; + } + + return Result; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -57,55 +202,78 @@ OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); - *Vbn = 0; - *Lbn = 0; - *SectorCount= 0; - return FALSE; -} - -/* - * @implemented - */ -BOOLEAN -NTAPI -FsRtlGetNextMcbEntry(IN PMCB Mcb, - IN ULONG RunIndex, - OUT PVBN Vbn, - OUT PLBN Lbn, - OUT PULONG SectorCount) -{ - BOOLEAN Return = FALSE; - LONGLONG llVbn; - LONGLONG llLbn; - LONGLONG llSectorCount; - - /* Call the Large version */ - Return = FsRtlGetNextLargeMcbEntry( - &Mcb->DummyFieldThatSizesThisStructureCorrectly, - RunIndex, - &llVbn, - &llLbn, - &llSectorCount); - - /* Return the lower 32 bits */ - *Vbn = (ULONG)llVbn; - *Lbn = (ULONG)llLbn; - *SectorCount = (ULONG)llSectorCount; - - /* And return the original value */ - return Return; -} - -/* - * @unimplemented + BOOLEAN Result; + + DPRINT("FsRtlGetNextLargeMcbEntry Mcb %x RunIndex %x\n", Mcb, RunIndex); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlGetNextBaseMcbEntry(&(Mcb->BaseMcb), + RunIndex, + Vbn, + Lbn, + SectorCount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlInitializeBaseMcb(IN PBASE_MCB Mcb, + IN POOL_TYPE PoolType) +{ + Mcb->PairCount = 0; + + if (PoolType == PagedPool) + { + Mcb->Mapping = ExAllocateFromPagedLookasideList(&FsRtlFirstMappingLookasideList); + } + else + { + Mcb->Mapping = ExAllocatePoolWithTag(PoolType | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), + 'FSBC'); + } + + Mcb->PoolType = PoolType; + Mcb->MaximumPairCount = MAXIMUM_PAIR_COUNT; + RtlInitializeGenericTable + (Mcb->Mapping, + (PRTL_GENERIC_COMPARE_ROUTINE)McbMappingCompare, + McbMappingAllocate, + McbMappingFree, + Mcb); + InitializeListHead(GET_LIST_HEAD(Mcb->Mapping)); +} + +/* + * @implemented */ VOID NTAPI FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, IN POOL_TYPE PoolType) { - KeBugCheck(FILE_SYSTEM); + Mcb->GuardedMutex = ExAllocateFromNPagedLookasideList(&FsRtlFastMutexLookasideList); + + KeInitializeGuardedMutex(Mcb->GuardedMutex); + + _SEH2_TRY + { + FsRtlInitializeBaseMcb(&(Mcb->BaseMcb), PoolType); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList, + Mcb->GuardedMutex); + Mcb->GuardedMutex = NULL; + } + _SEH2_END; }
/* @@ -113,16 +281,80 @@ */ VOID NTAPI -FsRtlInitializeMcb(IN PMCB Mcb, - IN POOL_TYPE PoolType) -{ - /* Call the newer function */ - FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, - PoolType); +FsRtlInitializeLargeMcbs(VOID) +{ + /* Initialize the list for the MCB */ + ExInitializePagedLookasideList(&FsRtlFirstMappingLookasideList, + NULL, + NULL, + POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), + IFS_POOL_TAG, + 0); /* FIXME: Should be 4 */ + + /* Initialize the list for the guarded mutex */ + ExInitializeNPagedLookasideList(&FsRtlFastMutexLookasideList, + NULL, + NULL, + POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(KGUARDED_MUTEX), + IFS_POOL_TAG, + 0); /* FIXME: Should be 32 */ }
/* * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlLookupBaseMcbEntry(IN PBASE_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) +{ + BOOLEAN Result = FALSE; + LARGE_MCB_MAPPING_ENTRY ToLookup; + PLARGE_MCB_MAPPING_ENTRY Entry; + + ToLookup.RunStartVbn.QuadPart = Vbn; + ToLookup.SectorCount.QuadPart = 1; + + Entry = RtlLookupElementGenericTable(Mcb->Mapping, &ToLookup); + if (!Entry) + { + // Find out if we have a following entry. The spec says we should return + // found with Lbn == -1 when we're beneath the largest map. + ToLookup.SectorCount.QuadPart = (1ull<<62) - ToLookup.RunStartVbn.QuadPart; + Entry = RtlLookupElementGenericTable(Mcb->Mapping, &ToLookup); + if (Entry) + { + Result = TRUE; + if (Lbn) *Lbn = ~0ull; + } + else + { + Result = FALSE; + } + } + else + { + LARGE_INTEGER Offset; + Offset.QuadPart = Vbn - Entry->RunStartVbn.QuadPart; + Result = TRUE; + if (Lbn) *Lbn = Entry->StartingLbn.QuadPart + Offset.QuadPart; + if (SectorCountFromLbn) *SectorCountFromLbn = Entry->SectorCount.QuadPart - Offset.QuadPart; + if (StartingLbn) *StartingLbn = Entry->StartingLbn.QuadPart; + if (SectorCountFromStartingLbn) *SectorCountFromStartingLbn = Entry->SectorCount.QuadPart; + } + + return Result; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -134,14 +366,61 @@ OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, OUT PULONG Index OPTIONAL) { - KeBugCheck(FILE_SYSTEM); - *Lbn = 0; - *SectorCountFromLbn = 0; - return FALSE; + BOOLEAN Result; + + DPRINT("FsRtlLookupLargeMcbEntry Mcb %x Vbn %x\n", Mcb, (ULONG)Vbn); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlLookupBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + Lbn, + SectorCountFromLbn, + StartingLbn, + SectorCountFromStartingLbn, + Index); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; }
/* * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastBaseMcbEntryAndIndex(IN PBASE_MCB OpaqueMcb, + IN OUT PLONGLONG LargeVbn, + IN OUT PLONGLONG LargeLbn, + IN OUT PULONG Index) +{ + ULONG i = 0; + BOOLEAN Result = FALSE; + PLIST_ENTRY ListEntry; + PLARGE_MCB_MAPPING_ENTRY Entry; + PLARGE_MCB_MAPPING_ENTRY CountEntry; + + ListEntry = GET_LIST_HEAD(OpaqueMcb->Mapping); + if (!IsListEmpty(ListEntry)) + { + Entry = CONTAINING_RECORD(ListEntry->Flink, LARGE_MCB_MAPPING_ENTRY, Sequence); + Result = TRUE; + *LargeVbn = Entry->RunStartVbn.QuadPart; + *LargeLbn = Entry->StartingLbn.QuadPart; + + for (i = 0, CountEntry = RtlEnumerateGenericTable(OpaqueMcb->Mapping, TRUE); + CountEntry != Entry; + CountEntry = RtlEnumerateGenericTable(OpaqueMcb->Mapping, FALSE)); + + *Index = i; + } + + return Result; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -150,15 +429,49 @@ OUT PLONGLONG LargeLbn, OUT PULONG Index) { - KeBugCheck(FILE_SYSTEM); - *LargeVbn = 0; - *LargeLbn = 0; - *Index = 0; - return FALSE; + BOOLEAN Result; + + DPRINT("FsRtlLookupLastLargeMcbEntryAndIndex %x\n", OpaqueMcb); + + KeAcquireGuardedMutex(OpaqueMcb->GuardedMutex); + Result = FsRtlLookupLastBaseMcbEntryAndIndex(&(OpaqueMcb->BaseMcb), + LargeVbn, + LargeLbn, + Index); + KeReleaseGuardedMutex(OpaqueMcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; }
/* * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastBaseMcbEntry(IN PBASE_MCB Mcb, + OUT PLONGLONG Vbn, + OUT PLONGLONG Lbn) +{ + BOOLEAN Result = FALSE; + PLIST_ENTRY ListEntry; + PLARGE_MCB_MAPPING_ENTRY Entry; + + ListEntry = GET_LIST_HEAD(Mcb->Mapping); + if (!IsListEmpty(ListEntry)) + { + Entry = CONTAINING_RECORD(ListEntry->Flink, LARGE_MCB_MAPPING_ENTRY, Sequence); + Result = TRUE; + *Vbn = Entry->RunStartVbn.QuadPart; + *Lbn = Entry->StartingLbn.QuadPart; + } + + return Result; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -166,68 +479,19 @@ OUT PLONGLONG Vbn, OUT PLONGLONG Lbn) { - KeBugCheck(FILE_SYSTEM); - return(FALSE); -} - -/* - * @implemented - */ -BOOLEAN -NTAPI -FsRtlLookupLastMcbEntry(IN PMCB Mcb, - OUT PVBN Vbn, - OUT PLBN Lbn) -{ - BOOLEAN Return = FALSE; - LONGLONG llVbn = 0; - LONGLONG llLbn = 0; - - /* Call the Large version */ - Return = FsRtlLookupLastLargeMcbEntry( - &Mcb->DummyFieldThatSizesThisStructureCorrectly, - &llVbn, - &llLbn); - - /* Return the lower 32-bits */ - *Vbn = (ULONG)llVbn; - *Lbn = (ULONG)llLbn; - - /* And return the original value */ - return Return; -} - -/* - * @implemented - */ -BOOLEAN -NTAPI -FsRtlLookupMcbEntry(IN PMCB Mcb, - IN VBN Vbn, - OUT PLBN Lbn, - OUT PULONG SectorCount OPTIONAL, - OUT PULONG Index) -{ - BOOLEAN Return = FALSE; - LONGLONG llLbn; - LONGLONG llSectorCount; - - /* Call the Large version */ - Return = FsRtlLookupLargeMcbEntry(&Mcb-> - DummyFieldThatSizesThisStructureCorrectly, - (LONGLONG)Vbn, - &llLbn, - &llSectorCount, - NULL, - NULL, - Index); - - /* Return the lower 32-bits */ - *Lbn = (ULONG)llLbn; - if (SectorCount) *SectorCount = (ULONG)llSectorCount; - - /* And return the original value */ - return Return; + BOOLEAN Result; + + DPRINT("FsRtlLookupLastLargeMcbEntry Mcb %x\n", Mcb); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlLookupLastBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + Lbn); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; }
/* @@ -235,33 +499,131 @@ */ ULONG NTAPI +FsRtlNumberOfRunsInBaseMcb(IN PBASE_MCB Mcb) +{ + /* Return the count */ + return Mcb->PairCount; +} + +/* + * @implemented + */ +ULONG +NTAPI FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb) { ULONG NumberOfRuns; + + DPRINT("FsRtlNumberOfRunsInLargeMcb Mcb %x\n", Mcb);
/* Read the number of runs while holding the MCB lock */ KeAcquireGuardedMutex(Mcb->GuardedMutex); NumberOfRuns = Mcb->BaseMcb.PairCount; KeReleaseGuardedMutex(Mcb->GuardedMutex);
+ DPRINT("Done %d\n", NumberOfRuns); + /* Return the count */ return NumberOfRuns; }
/* - * @implemented - */ -ULONG -NTAPI -FsRtlNumberOfRunsInMcb (IN PMCB Mcb) -{ - /* Call the newer function */ - return FsRtlNumberOfRunsInLargeMcb( - &Mcb->DummyFieldThatSizesThisStructureCorrectly); -} - -/* * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlRemoveBaseMcbEntry(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount) +{ + LARGE_MCB_MAPPING_ENTRY Node; + PLARGE_MCB_MAPPING_ENTRY Element; + + Node.RunStartVbn.QuadPart = Vbn; + Node.SectorCount.QuadPart = SectorCount; + + while ((Element = RtlLookupElementGenericTable(Mcb->Mapping, &Node))) + { + // Must split + if (Element->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart && + Element->SectorCount.QuadPart > Node.SectorCount.QuadPart) + { + LARGE_MCB_MAPPING_ENTRY Upper, Reinsert; + PLARGE_MCB_MAPPING_ENTRY Reinserted, Inserted; + LARGE_INTEGER StartHole = Node.RunStartVbn; + LARGE_INTEGER EndHole; + EndHole.QuadPart = Node.RunStartVbn.QuadPart + Node.SectorCount.QuadPart; + Upper.RunStartVbn.QuadPart = EndHole.QuadPart; + Upper.StartingLbn.QuadPart = + Element->StartingLbn.QuadPart + + EndHole.QuadPart - + Element->RunStartVbn.QuadPart; + Upper.SectorCount.QuadPart = + Element->SectorCount.QuadPart - + (EndHole.QuadPart - Element->RunStartVbn.QuadPart); + Reinsert = *Element; + Reinsert.SectorCount.QuadPart = + Element->RunStartVbn.QuadPart - StartHole.QuadPart; + RemoveEntryList(&Element->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + Mcb->PairCount--; + + Reinserted = RtlInsertElementGenericTable + (Mcb->Mapping, &Reinsert, sizeof(Reinsert), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); + Mcb->PairCount++; + + Inserted = RtlInsertElementGenericTable + (Mcb->Mapping, &Upper, sizeof(Upper), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Inserted->Sequence); + Mcb->PairCount++; + } + else if (Element->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) + { + LARGE_MCB_MAPPING_ENTRY NewElement; + PLARGE_MCB_MAPPING_ENTRY Reinserted; + LARGE_INTEGER StartHole = Node.RunStartVbn; + NewElement.RunStartVbn = Element->RunStartVbn; + NewElement.StartingLbn = Element->StartingLbn; + NewElement.SectorCount.QuadPart = StartHole.QuadPart - Element->StartingLbn.QuadPart; + + RemoveEntryList(&Element->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + Mcb->PairCount--; + + Reinserted = RtlInsertElementGenericTable + (Mcb->Mapping, &NewElement, sizeof(NewElement), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); + Mcb->PairCount++; + } + else + { + LARGE_MCB_MAPPING_ENTRY NewElement; + PLARGE_MCB_MAPPING_ENTRY Reinserted; + LARGE_INTEGER EndHole = Element->RunStartVbn; + LARGE_INTEGER EndRun; + EndRun.QuadPart = Element->RunStartVbn.QuadPart + Element->SectorCount.QuadPart; + NewElement.RunStartVbn = EndHole; + NewElement.StartingLbn.QuadPart = Element->StartingLbn.QuadPart + + (EndHole.QuadPart - Element->RunStartVbn.QuadPart); + NewElement.SectorCount.QuadPart = EndRun.QuadPart - EndHole.QuadPart; + + RemoveEntryList(&Element->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + Mcb->PairCount--; + + Reinserted = RtlInsertElementGenericTable + (Mcb->Mapping, &NewElement, sizeof(NewElement), NULL); + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Reinserted->Sequence); + Mcb->PairCount++; + } + } + + return TRUE; +} + +/* + * @implemented */ VOID NTAPI @@ -269,7 +631,15 @@ IN LONGLONG Vbn, IN LONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); + DPRINT("FsRtlRemoveLargeMcbEntry Mcb %x, Vbn %x, SectorCount %x\n", Mcb, (ULONG)Vbn, (ULONG)SectorCount); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + FsRtlRemoveBaseMcbEntry(&(Mcb->BaseMcb), + Vbn, + SectorCount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done\n"); }
/* @@ -277,29 +647,157 @@ */ VOID NTAPI -FsRtlRemoveMcbEntry(IN PMCB Mcb, - IN VBN Vbn, - IN ULONG SectorCount) -{ - /* Call the large function */ - FsRtlRemoveLargeMcbEntry(&Mcb->DummyFieldThatSizesThisStructureCorrectly, - (LONGLONG)Vbn, - (LONGLONG)SectorCount); -} - -/* - * @unimplemented +FsRtlResetBaseMcb(IN PBASE_MCB Mcb) +{ + PLARGE_MCB_MAPPING_ENTRY Element; + + while (RtlNumberGenericTableElements(Mcb->Mapping) && + (Element = (PLARGE_MCB_MAPPING_ENTRY)RtlGetElementGenericTable(Mcb->Mapping, 0))) + { + RtlDeleteElementGenericTable(Mcb->Mapping, Element); + } + + Mcb->PairCount = 0; + Mcb->MaximumPairCount = 0; +} + +/* + * @implemented */ VOID NTAPI FsRtlResetLargeMcb(IN PLARGE_MCB Mcb, IN BOOLEAN SelfSynchronized) { - KeBugCheck(FILE_SYSTEM); + if (!SelfSynchronized) + { + KeAcquireGuardedMutex(Mcb->GuardedMutex); + } + + FsRtlResetBaseMcb(&Mcb->BaseMcb); + + + if (!SelfSynchronized) + { + KeReleaseGuardedMutex(Mcb->GuardedMutex); + } +} + +#define MCB_BUMP_NO_MORE 0 +#define MCB_BUMP_AGAIN 1 + +static ULONG NTAPI McbBump(PBASE_MCB Mcb, PLARGE_MCB_MAPPING_ENTRY FixedPart) +{ + LARGE_MCB_MAPPING_ENTRY Reimagined; + PLARGE_MCB_MAPPING_ENTRY Found = NULL; + + DPRINT("McbBump %x (%x:%x)\n", Mcb, FixedPart->RunStartVbn.LowPart, FixedPart->SectorCount.LowPart); + + Reimagined = *FixedPart; + while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Reimagined))) + { + Reimagined = *Found; + Reimagined.RunStartVbn.QuadPart = + FixedPart->RunStartVbn.QuadPart + FixedPart->SectorCount.QuadPart; + DPRINT("Reimagined %x\n", Reimagined.RunStartVbn.LowPart); + } + + DPRINT("Found %x\n", Found); + if (!Found) return MCB_BUMP_NO_MORE; + DPRINT1 + ("Moving %x-%x to %x because %x-%x overlaps\n", + Found->RunStartVbn.LowPart, + Found->RunStartVbn.LowPart + Found->SectorCount.QuadPart, + Reimagined.RunStartVbn.LowPart + Reimagined.SectorCount.LowPart, + Reimagined.RunStartVbn.LowPart, + Reimagined.RunStartVbn.LowPart + Reimagined.SectorCount.LowPart); + Found->RunStartVbn.QuadPart = Reimagined.RunStartVbn.QuadPart + Reimagined.SectorCount.QuadPart; + Found->StartingLbn.QuadPart = Reimagined.StartingLbn.QuadPart + Reimagined.SectorCount.QuadPart; + + DPRINT("Again\n"); + return MCB_BUMP_AGAIN; }
/* * @unimplemented + */ +BOOLEAN +NTAPI +FsRtlSplitBaseMcb(IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG Amount) +{ + ULONG Result; + LARGE_MCB_MAPPING_ENTRY Node; + PLARGE_MCB_MAPPING_ENTRY Existing = NULL; + + Node.RunStartVbn.QuadPart = Vbn; + Node.SectorCount.QuadPart = 0; + + Existing = RtlLookupElementGenericTable(Mcb->Mapping, &Node); + + if (Existing) + { + // We're in the middle of a run + LARGE_MCB_MAPPING_ENTRY UpperPart; + LARGE_MCB_MAPPING_ENTRY LowerPart; + PLARGE_MCB_MAPPING_ENTRY InsertedUpper; + + UpperPart.RunStartVbn.QuadPart = Node.RunStartVbn.QuadPart + Amount; + UpperPart.SectorCount.QuadPart = Existing->RunStartVbn.QuadPart + + (Existing->SectorCount.QuadPart - Node.RunStartVbn.QuadPart); + UpperPart.StartingLbn.QuadPart = Existing->StartingLbn.QuadPart + + (Node.RunStartVbn.QuadPart - Existing->RunStartVbn.QuadPart); + LowerPart.RunStartVbn.QuadPart = Existing->RunStartVbn.QuadPart; + LowerPart.SectorCount.QuadPart = Node.RunStartVbn.QuadPart - Existing->RunStartVbn.QuadPart; + LowerPart.StartingLbn.QuadPart = Existing->StartingLbn.QuadPart; + + Node = UpperPart; + + DPRINT("Loop: %x\n", Node.RunStartVbn.LowPart); + while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN) + { + DPRINT("Node: %x\n", Node.RunStartVbn.LowPart); + } + DPRINT("Done\n"); + + if (Result == MCB_BUMP_NO_MORE) + { + Node = *Existing; + RemoveHeadList(&Existing->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Existing); + Mcb->PairCount--; + + // Adjust the element we found. + Existing->SectorCount = LowerPart.SectorCount; + + InsertedUpper = RtlInsertElementGenericTable + (Mcb->Mapping, &UpperPart, sizeof(UpperPart), NULL); + if (!InsertedUpper) + { + // Just make it like it was + Existing->SectorCount = Node.SectorCount; + return FALSE; + } + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &InsertedUpper->Sequence); + Mcb->PairCount++; + } + else + { + Node.RunStartVbn.QuadPart = Vbn; + Node.SectorCount.QuadPart = Amount; + while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN); + return Result == MCB_BUMP_NO_MORE; + } + } + + DPRINT("Done\n"); + + return TRUE; +} + +/* + * @implemented */ BOOLEAN NTAPI @@ -307,19 +805,62 @@ IN LONGLONG Vbn, IN LONGLONG Amount) { - KeBugCheck(FILE_SYSTEM); - return FALSE; + BOOLEAN Result; + + DPRINT("FsRtlSplitLargeMcb %x, Vbn %x, Amount %x\n", Mcb, (ULONG)Vbn, (ULONG)Amount); + + KeAcquireGuardedMutex(Mcb->GuardedMutex); + Result = FsRtlSplitBaseMcb(&(Mcb->BaseMcb), + Vbn, + Amount); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + + DPRINT("Done %d\n", Result); + + return Result; }
/* * @unimplemented + */ +VOID +NTAPI +FsRtlTruncateBaseMcb(IN PBASE_MCB Mcb, + IN LONGLONG Vbn) +{ + if (!Vbn) + { + FsRtlResetBaseMcb(Mcb); + } + else + { + LARGE_MCB_MAPPING_ENTRY Truncate; + PLARGE_MCB_MAPPING_ENTRY Found; + Truncate.RunStartVbn.QuadPart = Vbn; + Truncate.SectorCount.QuadPart = (1ull<<62) - Truncate.RunStartVbn.QuadPart; + while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Truncate))) + { + RemoveEntryList(&Found->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Found); + Mcb->PairCount--; + } + } +} + +/* + * @implemented */ VOID NTAPI FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, IN LONGLONG Vbn) { - KeBugCheck(FILE_SYSTEM); + DPRINT("FsRtlTruncateLargeMcb %x Vbn %x\n", Mcb, (ULONG)Vbn); + KeAcquireGuardedMutex(Mcb->GuardedMutex); + FsRtlTruncateBaseMcb(&(Mcb->BaseMcb), + Vbn); + KeReleaseGuardedMutex(Mcb->GuardedMutex); + DPRINT("Done\n"); }
/* @@ -327,32 +868,33 @@ */ VOID NTAPI -FsRtlTruncateMcb (IN PMCB Mcb, - IN VBN Vbn) -{ - /* Call the newer function */ - FsRtlTruncateLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, - (LONGLONG)Vbn); -} - -/* - * @unimplemented +FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb) +{ + FsRtlResetBaseMcb(Mcb); + + if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == MAXIMUM_PAIR_COUNT)) + { + ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList, + Mcb->Mapping); + } + else + { + ExFreePoolWithTag(Mcb->Mapping, 'FSBC'); + } +} + +/* + * @implemented */ VOID NTAPI FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb) { - KeBugCheck(FILE_SYSTEM); -} - -/* - * @implemented - */ -VOID -NTAPI -FsRtlUninitializeMcb(IN PMCB Mcb) -{ - /* Call the newer function */ - FsRtlUninitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly); -} - + if (Mcb->GuardedMutex) + { + ExFreeToNPagedLookasideList(&FsRtlFastMutexLookasideList, + Mcb->GuardedMutex); + FsRtlUninitializeBaseMcb(&(Mcb->BaseMcb)); + } +} +
Added: trunk/reactos/ntoskrnl/fsrtl/mcb.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/mcb.c?rev=55... ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/mcb.c (added) +++ trunk/reactos/ntoskrnl/fsrtl/mcb.c [iso-8859-1] Wed Feb 29 09:18:01 2012 @@ -1,0 +1,190 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/fsrtl/mcb.c + * PURPOSE: Mapped Control Block (MCB) support for File System Drivers + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include <ntoskrnl.h> +#define NDEBUG +#include <debug.h> + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlAddMcbEntry(IN PMCB Mcb, + IN VBN Vbn, + IN LBN Lbn, + IN ULONG SectorCount) +{ + /* Call the newer function */ + return FsRtlAddLargeMcbEntry(&Mcb-> + DummyFieldThatSizesThisStructureCorrectly, + (LONGLONG)Vbn, + (LONGLONG)Lbn, + (LONGLONG)SectorCount); +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlGetNextMcbEntry(IN PMCB Mcb, + IN ULONG RunIndex, + OUT PVBN Vbn, + OUT PLBN Lbn, + OUT PULONG SectorCount) +{ + BOOLEAN Return = FALSE; + LONGLONG llVbn; + LONGLONG llLbn; + LONGLONG llSectorCount; + + /* Call the Large version */ + Return = FsRtlGetNextLargeMcbEntry( + &Mcb->DummyFieldThatSizesThisStructureCorrectly, + RunIndex, + &llVbn, + &llLbn, + &llSectorCount); + + /* Return the lower 32 bits */ + *Vbn = (ULONG)llVbn; + *Lbn = (ULONG)llLbn; + *SectorCount = (ULONG)llSectorCount; + + /* And return the original value */ + return Return; +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlInitializeMcb(IN PMCB Mcb, + IN POOL_TYPE PoolType) +{ + /* Call the newer function */ + FsRtlInitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, + PoolType); +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlLookupLastMcbEntry(IN PMCB Mcb, + OUT PVBN Vbn, + OUT PLBN Lbn) +{ + BOOLEAN Return = FALSE; + LONGLONG llVbn = 0; + LONGLONG llLbn = 0; + + /* Call the Large version */ + Return = FsRtlLookupLastLargeMcbEntry( + &Mcb->DummyFieldThatSizesThisStructureCorrectly, + &llVbn, + &llLbn); + + /* Return the lower 32-bits */ + *Vbn = (ULONG)llVbn; + *Lbn = (ULONG)llLbn; + + /* And return the original value */ + return Return; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +FsRtlLookupMcbEntry(IN PMCB Mcb, + IN VBN Vbn, + OUT PLBN Lbn, + OUT PULONG SectorCount OPTIONAL, + OUT PULONG Index) +{ + BOOLEAN Return = FALSE; + LONGLONG llLbn; + LONGLONG llSectorCount; + + /* Call the Large version */ + Return = FsRtlLookupLargeMcbEntry(&Mcb-> + DummyFieldThatSizesThisStructureCorrectly, + (LONGLONG)Vbn, + &llLbn, + &llSectorCount, + NULL, + NULL, + Index); + + /* Return the lower 32-bits */ + *Lbn = (ULONG)llLbn; + if (SectorCount) *SectorCount = (ULONG)llSectorCount; + + /* And return the original value */ + return Return; +} + +/* + * @implemented + */ +ULONG +NTAPI +FsRtlNumberOfRunsInMcb(IN PMCB Mcb) +{ + /* Call the newer function */ + return FsRtlNumberOfRunsInLargeMcb( + &Mcb->DummyFieldThatSizesThisStructureCorrectly); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlRemoveMcbEntry(IN PMCB Mcb, + IN VBN Vbn, + IN ULONG SectorCount) +{ + /* Call the large function */ + FsRtlRemoveLargeMcbEntry(&Mcb->DummyFieldThatSizesThisStructureCorrectly, + (LONGLONG)Vbn, + (LONGLONG)SectorCount); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlTruncateMcb(IN PMCB Mcb, + IN VBN Vbn) +{ + /* Call the newer function */ + FsRtlTruncateLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly, + (LONGLONG)Vbn); +} + +/* + * @implemented + */ +VOID +NTAPI +FsRtlUninitializeMcb(IN PMCB Mcb) +{ + /* Call the newer function */ + FsRtlUninitializeLargeMcb(&Mcb->DummyFieldThatSizesThisStructureCorrectly); +}
Propchange: trunk/reactos/ntoskrnl/fsrtl/mcb.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/ntoskrnl/fsrtl/notify.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fsrtl/notify.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/fsrtl/notify.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/fsrtl/notify.c [iso-8859-1] Wed Feb 29 09:18:01 2012 @@ -12,6 +12,68 @@ #define NDEBUG #include <debug.h>
+/* PRIVATE FUNCTIONS *********************************************************/ + +PNOTIFY_CHANGE +FsRtlIsNotifyOnList(IN PLIST_ENTRY NotifyList, + IN PVOID FsContext) +{ + PLIST_ENTRY NextEntry; + PNOTIFY_CHANGE NotifyChange; + + if (!IsListEmpty(NotifyList)) + { + /* Browse the notifications list to find the matching entry */ + for (NextEntry = NotifyList->Flink; + NextEntry != NotifyList; + NextEntry = NextEntry->Flink) + { + NotifyChange = CONTAINING_RECORD(NextEntry, NOTIFY_CHANGE, NotifyList); + /* If the current record matches with the given context, it's the good one */ + if (NotifyChange->FsContext == FsContext) + { + return NotifyChange; + } + } + } + return NULL; +} + +VOID +FORCEINLINE +FsRtlNotifyAcquireFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync) +{ + ULONG_PTR CurrentThread = (ULONG_PTR)KeGetCurrentThread(); + + /* Only acquire fast mutex if it's not already acquired by the current thread */ + if (RealNotifySync->OwningThread != CurrentThread) + { + ExAcquireFastMutexUnsafe(&(RealNotifySync->FastMutex)); + RealNotifySync->OwningThread = CurrentThread; + } + /* Whatever the case, keep trace of the attempt to acquire fast mutex */ + RealNotifySync->OwnerCount++; +} + +VOID +FsRtlNotifyCompleteIrpList(IN PNOTIFY_CHANGE NotifyChange, + IN NTSTATUS Status) +{ +} + +VOID +FORCEINLINE +FsRtlNotifyReleaseFastMutex(IN PREAL_NOTIFY_SYNC RealNotifySync) +{ + RealNotifySync->OwnerCount--; + /* Release the fast mutex only if no other instance needs it */ + if (!RealNotifySync->OwnerCount) + { + ExReleaseFastMutexUnsafe(&(RealNotifySync->FastMutex)); + RealNotifySync->OwningThread = (ULONG_PTR)0; + } +} + /* PUBLIC FUNCTIONS **********************************************************/
/*++ @@ -44,8 +106,7 @@ * * @return None * - * @remarks This function only redirects to FsRtlNotifyFullChangeDirectory. - * So, it's better to call the entire function. + * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory. * *--*/ VOID @@ -58,32 +119,33 @@ IN ULONG CompletionFilter, IN PIRP NotifyIrp) { - FsRtlNotifyFullChangeDirectory(NotifySync, - NotifyList, - FsContext, - FullDirectoryName, - WatchTree, - TRUE, - CompletionFilter, - NotifyIrp, - NULL, - NULL); + FsRtlNotifyFilterChangeDirectory(NotifySync, + NotifyList, + FsContext, + FullDirectoryName, + WatchTree, + TRUE, + CompletionFilter, + NotifyIrp, + NULL, + NULL, + NULL); }
/*++ * @name FsRtlNotifyCleanup - * @unimplemented + * @implemented * * Called by FSD when all handles to FileObject (identified by FsContext) are closed * * @param NotifySync - * FILLME - * - * @param NotifyList - * FILLME + * Synchronization object pointer + * + * @param NotifyList + * Notify list pointer (to head) * * @param FsContext - * FILLME + * Used to identify the notify structure * * @return None * @@ -96,7 +158,67 @@ IN PLIST_ENTRY NotifyList, IN PVOID FsContext) { - KeBugCheck(FILE_SYSTEM); + PNOTIFY_CHANGE NotifyChange; + PREAL_NOTIFY_SYNC RealNotifySync; + PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL; + + /* Get real structure hidden behind the opaque pointer */ + RealNotifySync = (PREAL_NOTIFY_SYNC)NotifySync; + + /* Acquire the fast mutex */ + FsRtlNotifyAcquireFastMutex(RealNotifySync); + + _SEH2_TRY + { + /* Find if there's a matching notification with the FsContext */ + NotifyChange = FsRtlIsNotifyOnList(NotifyList, FsContext); + if (NotifyChange) + { + /* Mark it as to know that cleanup is in process */ + NotifyChange->Flags |= CLEANUP_IN_PROCESS; + + /* If there are pending IRPs, complete them using the STATUS_NOTIFY_CLEANUP status */ + if (!IsListEmpty(NotifyChange->NotifyIrps)) + { + FsRtlNotifyCompleteIrpList(NotifyChange, STATUS_NOTIFY_CLEANUP); + } + /* Remove from the list */ + RemoveEntryList(NotifyChange->NotifyList); + + /* Downcrease reference number and if 0 is reached, it's time to do complete cleanup */ + if (!InterlockedDecrement((PLONG)&(NotifyChange->ReferenceCount))) + { + /* In case there was an allocated buffer, free it */ + if (NotifyChange->AllocatedBuffer) + { + PsReturnProcessPagedPoolQuota(NotifyChange->OwningProcess, NotifyChange->ThisBufferLength); + ExFreePool(NotifyChange->AllocatedBuffer); + } + + /* In case there the string was set, get the captured subject security context */ + if (NotifyChange->FullDirectoryName) + { + SubjectContext = NotifyChange->SubjectContext; + } + + /* Finally, free the notification, as it's not needed anymore */ + ExFreePool(NotifyChange); + } + } + } + _SEH2_FINALLY + { + /* Release fast mutex */ + FsRtlNotifyReleaseFastMutex(RealNotifySync); + + /* If the subject security context was captured, release and free it */ + if (SubjectContext) + { + SeReleaseSubjectContext(SubjectContext); + ExFreePool(SubjectContext); + } + } + _SEH2_END; }
/*++ @@ -219,43 +341,46 @@
/*++ * @name FsRtlNotifyFullChangeDirectory - * @unimplemented - * - * FILLME - * - * @param NotifySync - * FILLME - * - * @param NotifyList - * FILLME + * @implemented + * + * Lets FSD know if changes occures in the specified directory. + * + * @param NotifySync + * Synchronization object pointer + * + * @param NotifyList + * Notify list pointer (to head) * * @param FsContext - * FILLME + * Used to identify the notify structure * * @param FullDirectoryName - * FILLME + * String (A or W) containing the full directory name * * @param WatchTree - * FILLME + * True to notify changes in subdirectories too * * @param IgnoreBuffer - * FILLME + * True to reenumerate directory. It's ignored it NotifyIrp is null * * @param CompletionFilter - * FILLME - * - * @param Irp - * FILLME + * Used to define types of changes to notify + * + * @param NotifyIrp + * IRP pointer to complete notify operation. It can be null * * @param TraverseCallback - * FILLME + * Pointer to a callback function. It's called each time a change is + * done in a subdirectory of the main directory. It's ignored it NotifyIrp + * is null * * @param SubjectContext - * FILLME - * - * @return None - * - * @remarks None + * Pointer to pass to SubjectContext member of TraverseCallback. + * It's freed after use. It's ignored it NotifyIrp is null + * + * @return None + * + * @remarks This function only redirects to FsRtlNotifyFilterChangeDirectory. * *--*/ VOID @@ -267,49 +392,60 @@ IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, - IN PIRP Irp, + IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL) { - KeBugCheck(FILE_SYSTEM); + FsRtlNotifyFilterChangeDirectory(NotifySync, + NotifyList, + FsContext, + FullDirectoryName, + WatchTree, + IgnoreBuffer, + CompletionFilter, + NotifyIrp, + TraverseCallback, + SubjectContext, + NULL); }
/*++ * @name FsRtlNotifyFullReportChange - * @unimplemented - * - * FILLME - * - * @param NotifySync - * FILLME - * - * @param NotifyList - * FILLME + * @implemented + * + * Complets the pending notify IRPs. + * + * @param NotifySync + * Synchronization object pointer + * + * @param NotifyList + * Notify list pointer (to head) * * @param FullTargetName - * FILLME + * String (A or W) containing the full directory name that changed * * @param TargetNameOffset - * FILLME + * Offset, in FullTargetName, of the final component that is in the changed directory * * @param StreamName - * FILLME + * String (A or W) containing a stream name * * @param NormalizedParentName - * FILLME + * String (A or W) containing the full directory name that changed with long names * * @param FilterMatch - * FILLME + * Flags that will be compared to the completion filter * * @param Action - * FILLME + * Action code to store in user's buffer * * @param TargetContext - * FILLME - * - * @return None - * - * @remarks None + * Pointer to a callback function. It's called each time a change is + * done in a subdirectory of the main directory. + * + * @return None + * + * @remarks This function only redirects to FsRtlNotifyFilterReportChange. * *--*/ VOID @@ -324,54 +460,73 @@ IN ULONG Action, IN PVOID TargetContext) { - KeBugCheck(FILE_SYSTEM); + FsRtlNotifyFilterReportChange(NotifySync, + NotifyList, + FullTargetName, + TargetNameOffset, + StreamName, + NormalizedParentName, + FilterMatch, + Action, + TargetContext, + NULL); }
/*++ * @name FsRtlNotifyInitializeSync - * @unimplemented - * - * FILLME - * - * @param NotifySync - * FILLME - * - * @return None - * - * @remarks None + * @implemented + * + * Allocates the internal structure associated with notifications. + * + * @param NotifySync + * Opaque pointer. It will receive the address of the allocated internal structure. + * + * @return None + * + * @remarks This function raise an exception in case of a failure. * *--*/ VOID NTAPI FsRtlNotifyInitializeSync(IN PNOTIFY_SYNC *NotifySync) { - KeBugCheck(FILE_SYSTEM); + PREAL_NOTIFY_SYNC RealNotifySync; + + *NotifySync = NULL; + + RealNotifySync = ExAllocatePoolWithTag(NonPagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, + sizeof(REAL_NOTIFY_SYNC), TAG('F', 'S', 'N', 'S')); + ExInitializeFastMutex(&(RealNotifySync->FastMutex)); + RealNotifySync->OwningThread = 0; + RealNotifySync->OwnerCount = 0; + + *NotifySync = RealNotifySync; }
/*++ * @name FsRtlNotifyReportChange - * @unimplemented - * - * FILLME - * - * @param NotifySync - * FILLME - * - * @param NotifyList - * FILLME + * @implemented + * + * Complets the pending notify IRPs. + * + * @param NotifySync + * Synchronization object pointer + * + * @param NotifyList + * Notify list pointer (to head) * * @param FullTargetName - * FILLME + * String (A or W) containing the full directory name that changed * * @param FileNamePartLength - * FILLME + * Length of the final component that is in the changed directory * * @param FilterMatch - * FILLME - * - * @return None - * - * @remarks None + * Flags that will be compared to the completion filter + * + * @return None + * + * @remarks This function only redirects to FsRtlNotifyFilterReportChange. * *--*/ VOID @@ -382,11 +537,20 @@ IN PUSHORT FileNamePartLength, IN ULONG FilterMatch) { - KeBugCheck(FILE_SYSTEM); -} - -/*++ - * @name FsRtlCurrentBatchOplock + FsRtlNotifyFilterReportChange(NotifySync, + NotifyList, + FullTargetName, + FullTargetName->Length - *FileNamePartLength, + NULL, + NULL, + FilterMatch, + 0, + NULL, + NULL); +} + +/*++ + * @name FsRtlNotifyUninitializeSync * @implemented * * Uninitialize a NOTIFY_SYNC object @@ -404,6 +568,10 @@ NTAPI FsRtlNotifyUninitializeSync(IN PNOTIFY_SYNC *NotifySync) { - KeBugCheck(FILE_SYSTEM); -} - + if (*NotifySync) + { + ExFreePoolWithTag(*NotifySync, TAG('F', 'S', 'N', 'S')); + *NotifySync = NULL; + } +} +
Modified: trunk/reactos/ntoskrnl/include/internal/fsrtl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/f... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/fsrtl.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/fsrtl.h [iso-8859-1] Wed Feb 29 09:18:01 2012 @@ -5,6 +5,10 @@ * PURPOSE: Internal header for the File System Runtime Library * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ + +#ifndef TAG +#define TAG(w,x,y,z) (((w)<<24)|((x)<<16)|((y)<<8)|(z)) +#endif
// // Define this if you want debugging support @@ -36,7 +40,7 @@ if (x & FsRtlpTraceLevel) DbgPrint(__VA_ARGS__) #endif #else -#define FSTRACE(x, fmt, ...) DPRINT(fmt, ##__VA_ARGS__) +#define FSTRACE(x, ...) DPRINT(__VA_ARGS__) #endif
// @@ -45,11 +49,67 @@ #define FSRTL_MAX_RESOURCES 16
// +// Number of maximum pair count per MCB +// +#define MAXIMUM_PAIR_COUNT 15 + +// +// Notifications flags +// +#define CLEANUP_IN_PROCESS 4 + +// +// Internal structure for NOTIFY_SYNC +// +typedef struct _REAL_NOTIFY_SYNC +{ + FAST_MUTEX FastMutex; + ULONG_PTR OwningThread; + ULONG OwnerCount; +} REAL_NOTIFY_SYNC, * PREAL_NOTIFY_SYNC; + +// +// Internal structure for notifications +// +typedef struct _NOTIFY_CHANGE +{ + PREAL_NOTIFY_SYNC NotifySync; + PVOID FsContext; + PVOID StreamID; + PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback; + PSECURITY_SUBJECT_CONTEXT SubjectContext; + PSTRING FullDirectoryName; + PLIST_ENTRY NotifyList; + PLIST_ENTRY NotifyIrps; + PFILTER_REPORT_CHANGE FilterCallback; + USHORT Flags; + UCHAR CharacterSize; + ULONG CompletionFilter; + PVOID AllocatedBuffer; + PVOID Buffer; + ULONG BufferLength; + ULONG ThisBufferLength; + ULONG DataLength; + ULONG LastEntry; + ULONG ReferenceCount; + PEPROCESS OwningProcess; +} NOTIFY_CHANGE, *PNOTIFY_CHANGE; + +// +// Internal structure for MCB Mapping pointer +// +typedef struct _INT_MAPPING +{ + VBN Vbn; + LBN Lbn; +} INT_MAPPING, *PINT_MAPPING; + +// // Initialization Routines // -BOOLEAN +VOID NTAPI -FsRtlInitSystem( +FsRtlInitializeLargeMcbs( VOID );
@@ -62,6 +122,12 @@ IN PFILE_OBJECT FileObject );
+BOOLEAN +NTAPI +FsRtlInitSystem( + VOID +); + // // Global data inside the File System Runtime Library //