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?…
==============================================================================
--- 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/large…
==============================================================================
--- 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(a)reactos.org)
* Pierre Schweitzer (heis_spiter(a)hotmail.com)
+ * Art Yerkes (art.yerkes(a)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');
}
}