[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / cache / section / data.c
index 3a9b849..a4982e3 100644 (file)
  *                  Herve Poussineau
  */
 
+/*
+
+A note on this code:
+
+Unlike the previous section code, this code does not rely on an active map
+for a page to exist in a data segment.  Each mapping contains a large integer
+offset to map at, and the segment always represents the entire section space
+from zero to the maximum long long.  This allows us to associate one single
+page map with each file object, and to let each mapping view an offset into
+the overall mapped file.  Temporarily unmapping the file has no effect on the
+section membership.
+
+This necessitates a change in the section page table implementation, which is
+now an RtlGenericTable.  This will be elaborated more in sptab.c.  One upshot
+of this change is that a mapping of a small files takes a bit more than 1/4
+of the size in nonpaged kernel space as it did previously.
+
+When we need other threads that may be competing for the same page fault to
+wait, we have a mechanism seperate from PageOps for dealing with that, which
+was suggested by Travis Geiselbrecht after a conversation I had with Alex
+Ionescu.  That mechanism is the MM_WAIT_ENTRY, which is the all-ones SWAPENTRY.
+
+When we wish for other threads to know that we're waiting and will finish
+handling a page fault, we place the swap entry MM_WAIT_ENTRY in the page table
+at the fault address (this works on either the section page table or a process
+address space), perform any blocking operations required, then replace the
+entry.
+
+*/
+
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
@@ -61,8 +91,6 @@ extern PMMWSL MmWorkingSetList;
 
 /* GLOBALS *******************************************************************/
 
-ULONG_PTR MmSubsectionBase;
-
 static const INFORMATION_CLASS_INFO ExSectionInfoClass[] =
 {
     ICI_SQ_SAME( sizeof(SECTION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* SectionBasicInformation */
@@ -129,7 +157,7 @@ MiZeroFillSection(PVOID Address, PLARGE_INTEGER FileOffsetPtr, ULONG Length)
     while (FileOffset.QuadPart < End.QuadPart)
     {
         PVOID Address;
-        ULONG Entry;
+        ULONG_PTR Entry;
 
         if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_CACHE, TRUE, &Page)))
             break;
@@ -163,6 +191,17 @@ MiZeroFillSection(PVOID Address, PLARGE_INTEGER FileOffsetPtr, ULONG Length)
     return STATUS_SUCCESS;
 }
 
+/*
+
+MiFlushMappedSection
+
+Called from cache code to cause dirty pages of a section
+to be written back.  This doesn't affect the mapping.
+
+BaseOffset is the base at which to start writing in file space.
+FileSize is the length of the file as understood by the cache.
+
+ */
 NTSTATUS
 NTAPI
 _MiFlushMappedSection(PVOID BaseAddress,
@@ -223,7 +262,7 @@ _MiFlushMappedSection(PVOID BaseAddress,
          PageAddress < EndingAddress;
          PageAddress += PAGE_SIZE)
     {
-        ULONG Entry;
+        ULONG_PTR Entry;
         FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress;
         Entry = MmGetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment,
                                              &FileOffset);
@@ -250,7 +289,7 @@ _MiFlushMappedSection(PVOID BaseAddress,
          PageAddress < EndingAddress;
          PageAddress += PAGE_SIZE)
     {
-        ULONG Entry;
+        ULONG_PTR Entry;
         FileOffset.QuadPart = ViewOffset.QuadPart + PageAddress - BeginningAddress;
         Entry = Pages[(PageAddress - BeginningAddress) >> PAGE_SHIFT];
         Page = PFN_FROM_SSE(Entry);
@@ -299,6 +338,13 @@ _MiFlushMappedSection(PVOID BaseAddress,
     return Status;
 }
 
+/*
+
+This deletes a segment entirely including its page map.
+It must have been unmapped in every address space.
+
+ */
+
 VOID
 NTAPI
 MmFinalizeSegment(PMM_SECTION_SEGMENT Segment)
@@ -346,12 +392,12 @@ MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject,
                      ULONG AllocationAttributes,
                      PFILE_OBJECT FileObject)
 /*
- * Create a section backed by a data file
+ * Create a section backed by a data file.
  */
 {
     PROS_SECTION_OBJECT Section;
     NTSTATUS Status;
-    ULARGE_INTEGER MaximumSize;
+    LARGE_INTEGER MaximumSize;
     PMM_SECTION_SEGMENT Segment;
     IO_STATUS_BLOCK Iosb;
     CC_FILE_SIZES FileSizes;
@@ -394,6 +440,7 @@ MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject,
     */
     if (!CcGetFileSizes(FileObject, &FileSizes))
     {
+        ULONG Information;
         /*
         * FIXME: This is propably not entirely correct. We can't look into
         * the standard FCB header because it might not be initialized yet
@@ -405,7 +452,8 @@ MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject,
                                         FileStandardInformation,
                                         sizeof(FILE_STANDARD_INFORMATION),
                                         &FileInfo,
-                                        &Iosb.Information);
+                                        &Information);
+        Iosb.Information = Information;
         DPRINT("Query => %x\n", Status);
 
         if (!NT_SUCCESS(Status))
@@ -507,7 +555,7 @@ MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject,
     {
         KeReleaseSpinLock(&FileObject->IrpListLock, OldIrql);
         DPRINTC("Free Segment %x\n", Segment);
-        ExFreePool(Segment);
+        ExFreePoolWithTag(Segment, TAG_MM_SECTION_SEGMENT);
 
         DPRINT("Filling out Segment info (previous data section)\n");
 
@@ -639,12 +687,19 @@ _MiMapViewOfSegment(PMMSUPPORT AddressSpace,
     return STATUS_SUCCESS;
 }
 
+/*
+
+Completely remove the page at FileOffset in Segment.  The page must not
+be mapped.
+
+*/
+
 VOID
 NTAPI
 MiFreeSegmentPage(PMM_SECTION_SEGMENT Segment,
                   PLARGE_INTEGER FileOffset)
 {
-    ULONG Entry;
+    ULONG_PTR Entry;
     PFILE_OBJECT FileObject = Segment->FileObject;
 
     Entry = MmGetPageEntrySectionSegment(Segment, FileOffset);
@@ -696,7 +751,7 @@ MmFreeCacheSectionPage(PVOID Context,
                        SWAPENTRY SwapEntry,
                        BOOLEAN Dirty)
 {
-    ULONG Entry;
+    ULONG_PTR Entry;
     PVOID *ContextData = Context;
     PMMSUPPORT AddressSpace;
     PEPROCESS Process;
@@ -812,7 +867,7 @@ MmExtendCacheSection(PROS_SECTION_OBJECT Section,
     MmLockSectionSegment(Segment);
     Segment->RawLength.QuadPart = NewSize->QuadPart;
     Segment->Length.QuadPart = MAX(Segment->Length.QuadPart,
-                                   PAGE_ROUND_UP(Segment->RawLength.LowPart));
+                                   (LONG64)PAGE_ROUND_UP(Segment->RawLength.QuadPart));
     MmUnlockSectionSegment(Segment);
     return STATUS_SUCCESS;
 }