- 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:
Hartmut Birr 2004-01-27 20:13:08 +00:00
parent 72a5d17432
commit 01723ab7ca

View file

@ -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;