Author: arty Date: Sat Nov 14 19:00:32 2009 New Revision: 44161
URL: http://svn.reactos.org/svn/reactos?rev=44161&view=rev Log: Untested implementation of large mcb (merging back).
Modified: branches/pierre-fsd/include/ddk/ntifs.h branches/pierre-fsd/ntoskrnl/fsrtl/largemcb.c
Modified: branches/pierre-fsd/include/ddk/ntifs.h URL: http://svn.reactos.org/svn/reactos/branches/pierre-fsd/include/ddk/ntifs.h?r... ============================================================================== --- branches/pierre-fsd/include/ddk/ntifs.h [iso-8859-1] (original) +++ branches/pierre-fsd/include/ddk/ntifs.h [iso-8859-1] Sat Nov 14 19:00:32 2009 @@ -25,7 +25,6 @@ #define _GNU_NTIFS_
#ifdef _NTOSKRNL_ -/* HACKHACKHACK!!! We shouldn't include this header from ntoskrnl! */ #define NTKERNELAPI #else #define NTKERNELAPI DECLSPEC_IMPORT @@ -44,13 +43,26 @@ #define VER_PRODUCTBUILD 10000 #endif
-#ifndef NTSYSAPI -#define NTSYSAPI -#endif - #define EX_PUSH_LOCK ULONG_PTR #define PEX_PUSH_LOCK PULONG_PTR
+ +#ifndef FlagOn +#define FlagOn(_F,_SF) ((_F) & (_SF)) +#endif + +#ifndef BooleanFlagOn +#define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0)) +#endif + +#ifndef SetFlag +#define SetFlag(_F,_SF) ((_F) |= (_SF)) +#endif + +#ifndef ClearFlag +#define ClearFlag(_F,_SF) ((_F) &= ~(_SF)) +#endif + #include "csq.h"
#ifdef _NTOSKRNL_ @@ -197,7 +209,10 @@ #define FILE_SUPPORTS_OBJECT_IDS 0x00010000 #define FILE_SUPPORTS_ENCRYPTION 0x00020000 #define FILE_NAMED_STREAMS 0x00040000 - +#define FILE_READ_ONLY_VOLUME 0x00080000 +#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000 +#define FILE_SUPPORTS_TRANSACTIONS 0x00200000 + #define FILE_PIPE_BYTE_STREAM_TYPE 0x00000000 #define FILE_PIPE_MESSAGE_TYPE 0x00000001
@@ -261,6 +276,7 @@ #define FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX (0x08) #define FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH (0x10) #define FSRTL_FLAG_USER_MAPPED_FILE (0x20) +#define FSRTL_FLAG_ADVANCED_HEADER (0x40) #define FSRTL_FLAG_EOF_ADVANCE_ACTIVE (0x80)
#define FSRTL_FLAG2_DO_MODIFIED_WRITE (0x01) @@ -317,8 +333,6 @@
#define MAILSLOT_SIZE_AUTO 0
-#define MAP_PROCESS 1L -#define MAP_SYSTEM 2L #define MEM_DOS_LIM 0x40000000
#define MCB_FLAG_RAISE_ON_ALLOCATION_FAILURE 1 @@ -933,10 +947,10 @@ UCHAR Revision; UCHAR Sbz1; SECURITY_DESCRIPTOR_CONTROL Control; - DWORD_PTR Owner; - DWORD_PTR Group; - DWORD_PTR Sacl; - DWORD_PTR Dacl; + ULONG Owner; + ULONG Group; + ULONG Sacl; + ULONG Dacl; } SECURITY_DESCRIPTOR_RELATIVE, *PISECURITY_DESCRIPTOR_RELATIVE; typedef enum _TOKEN_INFORMATION_CLASS { TokenUser=1,TokenGroups,TokenPrivileges,TokenOwner, @@ -1025,24 +1039,6 @@ WCHAR FileName[1]; } FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
-typedef struct _FILE_ID_BOTH_DIR_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - ULONG EaSize; - CCHAR ShortNameLength; - WCHAR ShortName[12]; - LARGE_INTEGER FileId; - WCHAR FileName[1]; -} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION; - typedef struct _FILE_COMPLETION_INFORMATION { HANDLE Port; PVOID Key; @@ -1090,8 +1086,42 @@ ULONG FileAttributes; ULONG FileNameLength; ULONG EaSize; - WCHAR FileName[0]; + WCHAR FileName[ANYSIZE_ARRAY]; } FILE_FULL_DIRECTORY_INFORMATION, *PFILE_FULL_DIRECTORY_INFORMATION; + +typedef struct _FILE_ID_FULL_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION; + +typedef struct _FILE_ID_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +} FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
typedef struct _FILE_EA_INFORMATION { ULONG EaSize; @@ -1177,22 +1207,6 @@ ULONG EaSize; WCHAR FileName[1]; } FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION; - -typedef struct _FILE_ID_FULL_DIR_INFORMATION { - ULONG NextEntryOffset; - ULONG FileIndex; - LARGE_INTEGER CreationTime; - LARGE_INTEGER LastAccessTime; - LARGE_INTEGER LastWriteTime; - LARGE_INTEGER ChangeTime; - LARGE_INTEGER EndOfFile; - LARGE_INTEGER AllocationSize; - ULONG FileAttributes; - ULONG FileNameLength; - ULONG EaSize; - LARGE_INTEGER FileId; - WCHAR FileName[1]; -} FILE_ID_FULL_DIR_INFORMATION, *PFILE_ID_FULL_DIR_INFORMATION;
typedef struct _FILE_GET_EA_INFORMATION { ULONG NextEntryOffset; @@ -1503,6 +1517,10 @@ } FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; #endif /* (VER_PRODUCTBUILD >= 2195) */
+#define FSRTL_FCB_HEADER_V0 (0x00) +#define FSRTL_FCB_HEADER_V1 (0x01) + + typedef struct _FSRTL_COMMON_FCB_HEADER { CSHORT NodeTypeCode; CSHORT NodeByteSize; @@ -1519,6 +1537,13 @@ LARGE_INTEGER ValidDataLength; } FSRTL_COMMON_FCB_HEADER, *PFSRTL_COMMON_FCB_HEADER;
+typedef enum _FSRTL_COMPARISON_RESULT +{ + LessThan = -1, + EqualTo = 0, + GreaterThan = 1 +} FSRTL_COMPARISON_RESULT; + #if (VER_PRODUCTBUILD >= 2600)
typedef struct _FSRTL_ADVANCED_FCB_HEADER { @@ -1897,6 +1922,63 @@ PRTL_AVL_FREE_ROUTINE FreeRoutine, PVOID TableContext ); + +NTSYSAPI +PVOID +NTAPI +RtlInsertElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer, + CLONG BufferSize, + PBOOLEAN NewElement OPTIONAL + ); + +NTSYSAPI +BOOLEAN +NTAPI +RtlDeleteElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer + ); + +NTSYSAPI +PVOID +NTAPI +RtlLookupElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + PVOID Buffer + ); + +NTSYSAPI +PVOID +NTAPI +RtlEnumerateGenericTableWithoutSplayingAvl ( + PRTL_AVL_TABLE Table, + PVOID *RestartKey + ); + +NTSYSAPI +PVOID +NTAPI +RtlEnumerateGenericTableAvl ( + PRTL_AVL_TABLE Table, + BOOLEAN Reset + ); + +NTSYSAPI +ULONG +NTAPI +RtlNumberGenericTableElementsAvl ( + PRTL_AVL_TABLE Table + ); + +NTSYSAPI +PVOID +NTAPI +RtlGetElementGenericTableAvl ( + PRTL_AVL_TABLE Table, + ULONG i + );
#if defined(USE_LPC6432) #define LPC_CLIENT_ID CLIENT_ID64 @@ -2321,7 +2403,7 @@ OUT PIO_STATUS_BLOCK IoStatus OPTIONAL );
-typedef VOID (*PDIRTY_PAGE_ROUTINE) ( +typedef VOID (NTAPI *PDIRTY_PAGE_ROUTINE) ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, @@ -2758,7 +2840,20 @@ #endif #endif /* (VER_PRODUCTBUILD >= 2600) */
-#define FlagOn(x, f) ((x) & (f)) + +#define FsRtlSetupAdvancedHeader( _advhdr, _fmutx ) \ +{ \ + SetFlag( (_advhdr)->Flags, FSRTL_FLAG_ADVANCED_HEADER ); \ + SetFlag( (_advhdr)->Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS ); \ + (_advhdr)->Version = FSRTL_FCB_HEADER_V1; \ + InitializeListHead( &(_advhdr)->FilterContexts ); \ + if ((_fmutx) != NULL) { \ + (_advhdr)->FastMutex = (_fmutx); \ + } \ + *((PULONG_PTR)(&(_advhdr)->PushLock)) = 0; \ + /*ExInitializePushLock( &(_advhdr)->PushLock ); API Not avaliable downlevel*/\ + (_advhdr)->FileContextSupportPointer = NULL; \ +}
NTKERNELAPI BOOLEAN @@ -3038,6 +3133,17 @@ IN PUNICODE_STRING Name );
+NTKERNELAPI +BOOLEAN +NTAPI +FsRtlIsFatDbcsLegal ( + IN ANSI_STRING DbcsName, + IN BOOLEAN WildCardsPermissible, + IN BOOLEAN PathNamePermissible, + IN BOOLEAN LeadingBackslashPermissible + ); + + #define FsRtlCompleteRequest(IRP,STATUS) { \ (IRP)->IoStatus.Status = (STATUS); \ IoCompleteRequest( (IRP), IO_DISK_INCREMENT ); \ @@ -3520,7 +3626,7 @@ IN PVOID FsContext );
-typedef BOOLEAN (*PCHECK_FOR_TRAVERSE_ACCESS) ( +typedef BOOLEAN (NTAPI *PCHECK_FOR_TRAVERSE_ACCESS) ( IN PVOID NotifyContext, IN PVOID TargetContext, IN PSECURITY_SUBJECT_CONTEXT SubjectContext @@ -3593,17 +3699,6 @@ NTAPI FsRtlNotifyInitializeSync ( IN PNOTIFY_SYNC *NotifySync -); - -NTKERNELAPI -VOID -NTAPI -FsRtlNotifyReportChange ( - IN PNOTIFY_SYNC NotifySync, - IN PLIST_ENTRY NotifyList, - IN PSTRING FullTargetName, - IN PUSHORT FileNamePartLength, - IN ULONG FilterMatch );
NTKERNELAPI @@ -3755,19 +3850,19 @@ NTKERNELAPI BOOLEAN NTAPI -FsRtlRemoveBaseMcbEntry ( - IN PBASE_MCB Mcb, - IN LONGLONG Vbn, - IN LONGLONG SectorCount -); - -NTKERNELAPI -VOID -NTAPI -FsRtlRemoveLargeMcbEntry ( - IN PLARGE_MCB Mcb, - IN LONGLONG Vbn, - IN LONGLONG SectorCount +FsRtlRemoveBaseMcbEntry( + IN PBASE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount +); + +NTKERNELAPI +VOID +NTAPI +FsRtlRemoveLargeMcbEntry( + IN PLARGE_MCB Mcb, + IN LONGLONG Vbn, + IN LONGLONG SectorCount );
NTKERNELAPI @@ -3884,13 +3979,6 @@ NTAPI FsRtlUninitializeOplock ( IN OUT POPLOCK Oplock -); - -NTHALAPI -VOID -NTAPI -HalDisplayString ( - IN PCHAR String );
NTKERNELAPI @@ -4003,6 +4091,32 @@ IoGetBaseFileSystemDeviceObject ( IN PFILE_OBJECT FileObject ); + +#if (VER_PRODUCTBUILD >= 2600) + +NTKERNELAPI +PDEVICE_OBJECT +NTAPI +IoGetDeviceAttachmentBaseRef ( + IN PDEVICE_OBJECT DeviceObject +); + +NTKERNELAPI +NTSTATUS +NTAPI +IoGetDiskDeviceObject ( + IN PDEVICE_OBJECT FileSystemDeviceObject, + OUT PDEVICE_OBJECT *DiskDeviceObject +); + +NTKERNELAPI +PDEVICE_OBJECT +NTAPI +IoGetLowerDeviceObject ( + IN PDEVICE_OBJECT DeviceObject +); + +#endif /* (VER_PRODUCTBUILD >= 2600) */
NTKERNELAPI PEPROCESS @@ -4988,6 +5102,24 @@ NTSYSAPI NTSTATUS NTAPI +RtlOemStringToCountedUnicodeString( + IN OUT PUNICODE_STRING DestinationString, + IN PCOEM_STRING SourceString, + IN BOOLEAN AllocateDestinationString +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlUnicodeStringToCountedOemString( + IN OUT POEM_STRING DestinationString, + IN PCUNICODE_STRING SourceString, + IN BOOLEAN AllocateDestinationString +); + +NTSYSAPI +NTSTATUS +NTAPI RtlReserveChunk ( IN USHORT CompressionFormat, IN OUT PUCHAR *CompressedBuffer, @@ -5065,6 +5197,17 @@ OUT PULONG BytesInMultiByteString OPTIONAL, IN PWCH UnicodeString, IN ULONG BytesInUnicodeString +); + +NTSYSAPI +NTSTATUS +NTAPI +RtlOemToUnicodeN( + OUT PWSTR UnicodeString, + IN ULONG MaxBytesInUnicodeString, + OUT PULONG BytesInUnicodeString OPTIONAL, + IN PCH OemString, + IN ULONG BytesInOemString );
/* RTL Splay Tree Functions */ @@ -5404,7 +5547,7 @@ ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->ClientToken : \ ((PSECURITY_SUBJECT_CONTEXT) SubjectContext)->PrimaryToken )
-typedef NTSTATUS (*PSE_LOGON_SESSION_TERMINATED_ROUTINE) ( +typedef NTSTATUS (NTAPI *PSE_LOGON_SESSION_TERMINATED_ROUTINE) ( IN PLUID LogonId );
Modified: branches/pierre-fsd/ntoskrnl/fsrtl/largemcb.c URL: http://svn.reactos.org/svn/reactos/branches/pierre-fsd/ntoskrnl/fsrtl/largem... ============================================================================== --- branches/pierre-fsd/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] (original) +++ branches/pierre-fsd/ntoskrnl/fsrtl/largemcb.c [iso-8859-1] Sat Nov 14 19:00:32 2009 @@ -5,6 +5,7 @@ * 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 ******************************************************************/ @@ -15,13 +16,50 @@
/* 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 @@ -30,8 +68,59 @@ IN LONGLONG Lbn, IN LONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); - return FALSE; + 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) + { + Existing = RtlInsertElementGenericTable + (Mcb->Mapping, &Node, sizeof(Node), &NewElement); + if (!Existing) break; + + if (!NewElement) + { + // We merge the existing runs + LARGE_INTEGER StartVbn, FinalVbn; + if (Existing->RunStartVbn.QuadPart < Node.RunStartVbn.QuadPart) + { + StartVbn = Existing->RunStartVbn; + Node.StartingLbn = Existing->StartingLbn; + } + else + { + StartVbn = Node.RunStartVbn; + } + 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; + } + Node.RunStartVbn.QuadPart = StartVbn.QuadPart; + Node.SectorCount.QuadPart = FinalVbn.QuadPart - StartVbn.QuadPart; + RemoveHeadList(&Existing->Sequence); + RtlDeleteElementGenericTable(Mcb->Mapping, Existing); + Mcb->PairCount--; + } + else + { + Mcb->MaximumPairCount++; + Mcb->PairCount++; + InsertHeadList(GET_LIST_HEAD(Mcb->Mapping), &Existing->Sequence); + } + } + + return !!Existing; }
/* @@ -45,6 +134,8 @@ IN LONGLONG SectorCount) { BOOLEAN Result; + + DPRINT1("Mcb %x Vbn %x Lbn %x SectorCount %x\n", Mcb, Vbn, Lbn, SectorCount);
KeAcquireGuardedMutex(Mcb->GuardedMutex); Result = FsRtlAddBaseMcbEntry(&(Mcb->BaseMcb), @@ -67,11 +158,26 @@ OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); - *Vbn = 0; - *Lbn = 0; - *SectorCount= 0; - return FALSE; + 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; }
/* @@ -115,12 +221,19 @@ else { Mcb->Mapping = ExAllocatePoolWithTag(PoolType | POOL_RAISE_IF_ALLOCATION_FAILURE, - sizeof(INT_MAPPING) * MAXIMUM_PAIR_COUNT, - TAG('F', 'S', 'B', 'C')); + 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)); }
/* @@ -160,7 +273,7 @@ NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, - sizeof(INT_MAPPING) * MAXIMUM_PAIR_COUNT, + sizeof(RTL_GENERIC_TABLE) + sizeof(LIST_ENTRY), IFS_POOL_TAG, 0); /* FIXME: Should be 4 */
@@ -187,10 +300,42 @@ OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, OUT PULONG Index OPTIONAL) { - KeBugCheck(FILE_SYSTEM); - *Lbn = 0; - *SectorCountFromLbn = 0; - return FALSE; + 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; }
/* @@ -231,11 +376,28 @@ IN OUT PLONGLONG LargeLbn, IN OUT PULONG Index) { - KeBugCheck(FILE_SYSTEM); - *LargeVbn = 0; - *LargeLbn = 0; - *Index = 0; - return FALSE; + 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; }
/* @@ -269,8 +431,20 @@ OUT PLONGLONG Vbn, OUT PLONGLONG Lbn) { - KeBugCheck(FILE_SYSTEM); - return FALSE; + 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; }
/* @@ -331,8 +505,90 @@ IN LONGLONG Vbn, IN LONGLONG SectorCount) { - KeBugCheck(FILE_SYSTEM); - return FALSE; + 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; }
/* @@ -358,7 +614,16 @@ NTAPI FsRtlResetBaseMcb(IN PBASE_MCB Mcb) { - Mcb->PairCount = 0; + 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; }
/* @@ -372,13 +637,44 @@ if (!SelfSynchronized) { KeAcquireGuardedMutex(Mcb->GuardedMutex); - Mcb->BaseMcb.PairCount = 0; - KeReleaseGuardedMutex(Mcb->GuardedMutex); + } + + FsRtlResetBaseMcb(&Mcb->BaseMcb); + + + if (!SelfSynchronized) + { + KeReleaseGuardedMutex(Mcb->GuardedMutex); } - else - { - Mcb->BaseMcb.PairCount = 0; - } +} + +#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; + + Reimagined = *FixedPart; + while ((Found = RtlLookupElementGenericTable(Mcb->Mapping, &Reimagined))) + { + Reimagined = *Found; + Reimagined.RunStartVbn.QuadPart = + FixedPart->RunStartVbn.QuadPart + FixedPart->SectorCount.QuadPart; + } + + 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; + return MCB_BUMP_AGAIN; }
/* @@ -390,8 +686,66 @@ IN LONGLONG Vbn, IN LONGLONG Amount) { - KeBugCheck(FILE_SYSTEM); - return FALSE; + 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; + + while ((Result = McbBump(Mcb, &Node)) == MCB_BUMP_AGAIN); + + 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; + } + } + + return TRUE; }
/* @@ -422,7 +776,23 @@ FsRtlTruncateBaseMcb(IN PBASE_MCB Mcb, IN LONGLONG Vbn) { - KeBugCheck(FILE_SYSTEM); + 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--; + } + } }
/* @@ -446,6 +816,8 @@ NTAPI FsRtlUninitializeBaseMcb(IN PBASE_MCB Mcb) { + FsRtlResetBaseMcb(Mcb); + if ((Mcb->PoolType == PagedPool) && (Mcb->MaximumPairCount == MAXIMUM_PAIR_COUNT)) { ExFreeToPagedLookasideList(&FsRtlFirstMappingLookasideList, @@ -453,7 +825,7 @@ } else { - ExFreePoolWithTag(Mcb->Mapping, TAG('F', 'S', 'B', 'C')); + ExFreePoolWithTag(Mcb->Mapping, 'FSBC'); } }