mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 22:02:58 +00:00
- Fixed some problems which occurs if a read only segment is
changed to write and back to read only and if such a segment (or a page from such a segment) is paged out and reloaded again. svn path=/trunk/; revision=7890
This commit is contained in:
parent
72a5d17432
commit
01723ab7ca
1 changed files with 119 additions and 127 deletions
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: section.c,v 1.141 2004/01/05 14:28:21 weiden Exp $
|
/* $Id: section.c,v 1.142 2004/01/27 20:13:08 hbirr Exp $
|
||||||
*
|
*
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: ntoskrnl/mm/section.c
|
* FILE: ntoskrnl/mm/section.c
|
||||||
|
@ -379,35 +379,39 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MmSetSavedSwapEntryPage(Page, 0);
|
|
||||||
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
|
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
|
||||||
(Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
|
(Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED))
|
||||||
{
|
{
|
||||||
if (Dirty && !PageOut)
|
if (!PageOut)
|
||||||
{
|
{
|
||||||
/*
|
if (Dirty)
|
||||||
* FIXME:
|
{
|
||||||
* We hold all locks. Nobody can do something with the current
|
/*
|
||||||
* process and the current segment (also not within an other process).
|
* FIXME:
|
||||||
*/
|
* We hold all locks. Nobody can do something with the current
|
||||||
NTSTATUS Status;
|
* process and the current segment (also not within an other process).
|
||||||
PMDL Mdl;
|
*/
|
||||||
Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
|
NTSTATUS Status;
|
||||||
MmBuildMdlFromPages(Mdl, (PULONG)&Page);
|
PMDL Mdl;
|
||||||
Status = MmWriteToSwapPage(SavedSwapEntry, Mdl);
|
Mdl = MmCreateMdl(NULL, NULL, PAGE_SIZE);
|
||||||
if (!NT_SUCCESS(Status))
|
MmBuildMdlFromPages(Mdl, (PULONG)&Page);
|
||||||
{
|
Status = MmWriteToSwapPage(SavedSwapEntry, Mdl);
|
||||||
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
|
if (!NT_SUCCESS(Status))
|
||||||
}
|
{
|
||||||
|
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
|
||||||
|
MmSetSavedSwapEntryPage(Page, 0);
|
||||||
}
|
}
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
|
MmReleasePageMemoryConsumer(MC_USER, Page);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MmSetPageEntrySectionSegment(Segment, Offset, 0);
|
DPRINT1("Found a swapentry for a non private page in an image or data file sgment\n");
|
||||||
MmFreeSwapPage(SavedSwapEntry);
|
KEBUGCHECK(0);
|
||||||
}
|
}
|
||||||
MmReleasePageMemoryConsumer(MC_USER, Page);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -623,6 +627,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
PMM_PAGEOP PageOp;
|
PMM_PAGEOP PageOp;
|
||||||
PMM_REGION Region;
|
PMM_REGION Region;
|
||||||
|
BOOL HasSwapEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is a window between taking the page fault and locking the
|
* There is a window between taking the page fault and locking the
|
||||||
|
@ -726,15 +731,20 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
if (!MmIsPagePresent(AddressSpace->Process, Address))
|
if (!MmIsPagePresent(AddressSpace->Process, Address))
|
||||||
{
|
{
|
||||||
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
|
Entry = MmGetPageEntrySectionSegment(Segment, Offset);
|
||||||
if (Entry == 0)
|
HasSwapEntry = MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress);
|
||||||
{
|
|
||||||
MmUnlockSectionSegment(Segment);
|
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
{
|
||||||
return(STATUS_MM_RESTART_OPERATION);
|
/*
|
||||||
}
|
* The page was a private page in another or in our address space
|
||||||
|
*/
|
||||||
|
MmUnlockSectionSegment(Segment);
|
||||||
|
MmspCompleteAndReleasePageOp(PageOp);
|
||||||
|
return(STATUS_MM_RESTART_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
Page.QuadPart = (LONGLONG)(PAGE_FROM_SSE(Entry));
|
Page.QuadPart = (LONGLONG)(PAGE_FROM_SSE(Entry));
|
||||||
MmReferencePage(Page);
|
|
||||||
MmSharePageEntrySectionSegment(Segment, Offset);
|
MmSharePageEntrySectionSegment(Segment, Offset);
|
||||||
|
|
||||||
Status = MmCreateVirtualMapping(MemoryArea->Process,
|
Status = MmCreateVirtualMapping(MemoryArea->Process,
|
||||||
|
@ -771,11 +781,12 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
HasSwapEntry = MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress);
|
||||||
* Must be private page we have swapped out.
|
if (HasSwapEntry)
|
||||||
*/
|
|
||||||
if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress))
|
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Must be private page we have swapped out.
|
||||||
|
*/
|
||||||
SWAPENTRY SwapEntry;
|
SWAPENTRY SwapEntry;
|
||||||
PMDL Mdl;
|
PMDL Mdl;
|
||||||
|
|
||||||
|
@ -1506,51 +1517,6 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
Context.Private = FALSE;
|
Context.Private = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Paging out data mapped read-only is easy.
|
|
||||||
*/
|
|
||||||
if (Context.Segment->Protection & (PAGE_READONLY|PAGE_EXECUTE_READ))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Read-only data should never be in the swapfile.
|
|
||||||
*/
|
|
||||||
if (SwapEntry != 0)
|
|
||||||
{
|
|
||||||
DPRINT1("SwapEntry != 0 was 0x%.8X at address 0x%.8X, "
|
|
||||||
"paddress 0x%.8X\n", SwapEntry, Address,
|
|
||||||
PhysicalAddress);
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read-only data should never be COWed
|
|
||||||
*/
|
|
||||||
if (Context.Private)
|
|
||||||
{
|
|
||||||
DPRINT1("Had private copy of read-only page.\n");
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete all mappings of this page.
|
|
||||||
*/
|
|
||||||
MmDeleteAllRmaps(PhysicalAddress, (PVOID)&Context,
|
|
||||||
MmPageOutDeleteMapping);
|
|
||||||
if (Context.WasDirty)
|
|
||||||
{
|
|
||||||
DPRINT1("Had a dirty page of a read-only page.\n");
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Otherwise we have read-write data.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take an additional reference to the page or the cache segment.
|
* Take an additional reference to the page or the cache segment.
|
||||||
*/
|
*/
|
||||||
|
@ -1590,69 +1556,87 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
* we can't free the page at this point.
|
* we can't free the page at this point.
|
||||||
*/
|
*/
|
||||||
SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
|
SwapEntry = MmGetSavedSwapEntryPage(PhysicalAddress);
|
||||||
if (!Context.WasDirty &&
|
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT)
|
||||||
!(SwapEntry == 0 &&
|
|
||||||
(Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
|
|
||||||
Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED)))
|
|
||||||
{
|
{
|
||||||
if (Context.Private)
|
if (Context.Private)
|
||||||
{
|
|
||||||
if (!(Context.Segment->Characteristics & IMAGE_SECTION_CHAR_BSS) &&
|
|
||||||
SwapEntry == 0)
|
|
||||||
{
|
|
||||||
DPRINT1("Private page, non-dirty but not swapped out "
|
|
||||||
"process %d address 0x%.8X\n",
|
|
||||||
AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0,
|
|
||||||
Address);
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SwapEntry != 0)
|
|
||||||
{
|
|
||||||
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
|
|
||||||
Status = MmCreatePageFileMapping(AddressSpace->Process,
|
|
||||||
Address,
|
|
||||||
SwapEntry);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (DirectMapped && !Context.Private)
|
|
||||||
{
|
{
|
||||||
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
|
DPRINT1("Found a %s private page (address %x) in a pagefile segment.\n",
|
||||||
if (!NT_SUCCESS(Status))
|
Context.WasDirty ? "dirty" : "clean", Address);
|
||||||
{
|
KEBUGCHECK(0);
|
||||||
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
|
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
if (!Context.WasDirty && SwapEntry != 0)
|
||||||
{
|
{
|
||||||
|
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
|
||||||
|
MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
||||||
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
MmspCompleteAndReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED)
|
||||||
|
{
|
||||||
|
if (Context.Private)
|
||||||
|
{
|
||||||
|
DPRINT1("Found a %s private page (address %x) in a shared section segment.\n",
|
||||||
|
Context.WasDirty ? "dirty" : "clean", Address);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
if (!Context.WasDirty || SwapEntry != 0)
|
||||||
|
{
|
||||||
|
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
|
||||||
|
if (SwapEntry != 0)
|
||||||
|
{
|
||||||
|
MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
||||||
|
}
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
MmspCompleteAndReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!Context.Private && DirectMapped)
|
||||||
|
{
|
||||||
|
if (SwapEntry != 0)
|
||||||
|
{
|
||||||
|
DPRINT1("Found a swapentry for a non private and direct mapped page (address %x)\n",
|
||||||
|
Address);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
|
||||||
|
KEBUGCHECK(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
MmspCompleteAndReleasePageOp(PageOp);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
else if (!Context.WasDirty && !DirectMapped && !Context.Private)
|
||||||
/*
|
|
||||||
* If this page was direct mapped from the cache then the cache manager
|
|
||||||
* will already have taken care of writing it back.
|
|
||||||
*/
|
|
||||||
if (DirectMapped && !Context.Private)
|
|
||||||
{
|
{
|
||||||
assert(SwapEntry == 0);
|
if (SwapEntry != 0)
|
||||||
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
|
{
|
||||||
|
DPRINT1("Found a swap entry for a non dirty, non private and not direct mapped page (address %x)\n",
|
||||||
|
Address);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
|
MmspCompleteAndReleasePageOp(PageOp);
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
|
||||||
|
{
|
||||||
|
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
|
||||||
|
Status = MmCreatePageFileMapping(AddressSpace->Process,
|
||||||
|
Address,
|
||||||
|
SwapEntry);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("CcRosUnmapCacheSegment failed, status = %x\n", Status);
|
KEBUGCHECK(0);
|
||||||
KEBUGCHECK(0);
|
|
||||||
}
|
}
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
PageOp->Status = STATUS_SUCCESS;
|
PageOp->Status = STATUS_SUCCESS;
|
||||||
MmspCompleteAndReleasePageOp(PageOp);
|
MmspCompleteAndReleasePageOp(PageOp);
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
|
@ -1758,7 +1742,15 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
|
||||||
*/
|
*/
|
||||||
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress);
|
DPRINT("MM: Wrote section page 0x%.8X to swap!\n", PhysicalAddress);
|
||||||
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
|
MmSetSavedSwapEntryPage(PhysicalAddress, 0);
|
||||||
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
|
||||||
|
Context.Segment->Characteristics & IMAGE_SECTION_CHAR_SHARED)
|
||||||
|
{
|
||||||
|
MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
if (Context.Private)
|
if (Context.Private)
|
||||||
{
|
{
|
||||||
|
@ -2561,7 +2553,7 @@ MmCreateDataFileSection(PHANDLE SectionHandle,
|
||||||
FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
|
FileObject->SectionObjectPointer->DataSectionObject = (PVOID)Segment;
|
||||||
|
|
||||||
Segment->FileOffset = 0;
|
Segment->FileOffset = 0;
|
||||||
Segment->Protection = 0;
|
Segment->Protection = SectionPageProtection;
|
||||||
Segment->Attributes = 0;
|
Segment->Attributes = 0;
|
||||||
Segment->Flags = MM_DATAFILE_SEGMENT;
|
Segment->Flags = MM_DATAFILE_SEGMENT;
|
||||||
Segment->Characteristics = 0;
|
Segment->Characteristics = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue