- 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,11 +379,12 @@ 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: * FIXME:
@ -398,16 +399,19 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status); DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
KEBUGCHECK(0);
} }
} }
MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry)); MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
MmSetSavedSwapEntryPage(Page, 0);
}
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);
if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
{ {
/*
* The page was a private page in another or in our address space
*/
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);
MmspCompleteAndReleasePageOp(PageOp); MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_MM_RESTART_OPERATION); 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);
if (HasSwapEntry)
{
/* /*
* Must be private page we have swapped out. * Must be private page we have swapped out.
*/ */
if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress))
{
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,25 +1556,77 @@ 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) && DPRINT1("Found a %s private page (address %x) in a pagefile segment.\n",
SwapEntry == 0) Context.WasDirty ? "dirty" : "clean", Address);
KEBUGCHECK(0);
}
if (!Context.WasDirty && SwapEntry != 0)
{ {
DPRINT1("Private page, non-dirty but not swapped out " MmSetSavedSwapEntryPage(PhysicalAddress, 0);
"process %d address 0x%.8X\n", MmSetPageEntrySectionSegment(Context.Segment, Context.Offset, MAKE_SWAP_SSE(SwapEntry));
AddressSpace->Process ? AddressSpace->Process->UniqueProcessId : 0, 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); Address);
KEBUGCHECK(0); KEBUGCHECK(0);
} }
else Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
KEBUGCHECK(0);
}
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS);
}
else if (!Context.WasDirty && !DirectMapped && !Context.Private)
{ {
if (SwapEntry != 0) if (SwapEntry != 0)
{
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); MmSetSavedSwapEntryPage(PhysicalAddress, 0);
Status = MmCreatePageFileMapping(AddressSpace->Process, Status = MmCreatePageFileMapping(AddressSpace->Process,
@ -1618,41 +1636,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
{ {
KEBUGCHECK(0); KEBUGCHECK(0);
} }
}
}
}
if (DirectMapped && !Context.Private)
{
Status = CcRosUnmapCacheSegment(Bcb, FileOffset, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1("CCRosUnmapCacheSegment failed, status = %x\n", Status);
KEBUGCHECK(0);
}
}
else
{
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
}
PageOp->Status = STATUS_SUCCESS;
MmspCompleteAndReleasePageOp(PageOp);
return(STATUS_SUCCESS);
}
/*
* 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);
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);
@ -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);
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); 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;