--- a/kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp Thu Aug 12 11:55:14 2010 +0100
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp Thu Aug 12 12:51:24 2010 +0100
@@ -67,7 +67,7 @@
enum TSwapState
{
EStateUnreserved = 0, ///< swap space not yet reserved, or page is being decommitted
- EStateBlank = 1, ///< swap page has never been written
+ EStateBlank = 1, ///< swap page has never been written or the last write failed
EStateWritten = 2, ///< swap page has been written out at least once
EStateWriting = 3 ///< swap page is in the process of being written out
};
@@ -231,7 +231,7 @@
inline DSwapManager::TSwapState DSwapManager::SwapState(TUint aSwapData)
{
TSwapState state = (TSwapState)(aSwapData & ESwapStateMask);
- __NK_ASSERT_DEBUG(state >= EStateWritten || (aSwapData & ~ESwapStateMask) == 0);
+ __NK_ASSERT_DEBUG(state >= EStateBlank || aSwapData == 0);
return state;
}
@@ -244,6 +244,7 @@
inline TUint DSwapManager::SwapData(TSwapState aSwapState, TInt aSwapIndex)
{
+ __NK_ASSERT_DEBUG(aSwapIndex < (1 << (32 - ESwapIndexShift)));
return (aSwapIndex << ESwapIndexShift) | aSwapState;
}
@@ -464,7 +465,6 @@
{
__ASSERT_CRITICAL;
- TInt r = KErrNone;
const TUint readUnitShift = iDevice->iReadUnitShift;
TUint readSize = KPageSize >> readUnitShift;
TThreadMessage message;
@@ -477,24 +477,36 @@
MmuLock::Lock(); // MmuLock required for atomic access to manager data.
TUint swapData = aMemory->PagingManagerData(index);
TSwapState state = SwapState(swapData);
+ TUint swapPage = SwapIndex(swapData);
if (state == EStateUnreserved)
- {// This page is not committed to the memory object
+ {
+ // This page is not committed to the memory object
MmuLock::Unlock();
return KErrNotFound;
}
else if (state == EStateBlank)
- {// This page has not been written to yet so don't read from swap
- // just wipe it if required.
- TUint allocFlags = aMemory->RamAllocFlags();
- MmuLock::Unlock();
- TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe);
- if (wipePages)
+ {
+ if (swapPage != 0)
+ {
+ // An error occured while writing the page out, so report it now
+ MmuLock::Unlock();
+ return -swapPage;
+ }
+ else
{
- TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ?
- (allocFlags >> Mmu::EAllocWipeByteShift) & 0xff :
- 0x03;
- memset((TAny*)aLinAddr, wipeByte, KPageSize);
+ // This page has not been written to yet so don't read from swap
+ // just wipe it if required.
+ TUint allocFlags = aMemory->RamAllocFlags();
+ MmuLock::Unlock();
+ TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe);
+ if (wipePages)
+ {
+ TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ?
+ (allocFlags >> Mmu::EAllocWipeByteShift) & 0xff :
+ 0x03;
+ memset((TAny*)aLinAddr, wipeByte, KPageSize);
+ }
}
}
else
@@ -506,19 +518,21 @@
// OK to release as if the object's data is decommitted the pager
// will check that data is still valid before mapping it.
MmuLock::Unlock();
- TUint readStart = (SwapIndex(swapData) << KPageShift) >> readUnitShift;
+ TUint readStart = (swapPage << KPageShift) >> readUnitShift;
START_PAGING_BENCHMARK;
- r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging);
+ TInt r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging);
+ END_PAGING_BENCHMARK(EPagingBmReadDataMedia);
+ __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore shouldn't fail with KErrNoMemory
if (r != KErrNone)
- __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r));
- __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
- END_PAGING_BENCHMARK(EPagingBmReadDataMedia);
- __NK_ASSERT_ALWAYS(r == KErrNone);
+ __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r));
+ r = ThePager.EmbedErrorContext(EPagingErrorContextDataRead, r);
+ if (r != KErrNone)
+ return r;
}
END_PAGING_BENCHMARK(EPagingBmReadDataPage);
}
-
- return r;
+
+ return KErrNone;
}
@@ -626,14 +640,16 @@
r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground);
else
r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground);
+ END_PAGING_BENCHMARK(EPagingBmWriteDataMedia);
if (r != KErrNone)
{
__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r));
+ if (r > 0)
+ r = KErrGeneral;
}
__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
- __NK_ASSERT_ALWAYS(r == KErrNone);
- END_PAGING_BENCHMARK(EPagingBmWriteDataMedia);
+ r = ThePager.EmbedErrorContext(EPagingErrorContextDataWrite, r);
TUint i;
TUint swapData[KMaxPagesToClean];
@@ -647,8 +663,12 @@
__NK_ASSERT_DEBUG(s == EStateUnreserved || s == EStateWriting);
if (s == EStateWriting)
{
- // Store the new swap location and mark the page as saved.
- aMemory[i]->SetPagingManagerData(aIndex[i], SwapData(EStateWritten, aSwapIndex + i));
+ // Store the new swap location and mark the page as saved, or if an error occured then
+ // record the error code instead
+ TUint swapData = (r == KErrNone)
+ ? SwapData(EStateWritten, aSwapIndex + i)
+ : SwapData(EStateBlank, -r);
+ aMemory[i]->SetPagingManagerData(aIndex[i], swapData);
}
}
MmuLock::Unlock();
@@ -656,15 +676,17 @@
for (i = 0 ; i < aCount ; ++i)
{
TSwapState s = SwapState(swapData[i]);
- if (s == EStateUnreserved)
+ if (s == EStateUnreserved || s == EStateBlank)
{
- // The page was decommitted while we were cleaning it, so free the swap page we
- // allocated and continue, leaving this page in the unreserved state.
+ // The page was either decommitted while we were cleaning it, or an error occured while
+ // writing. Free the swap page and don't modify the state.
FreeSwapIndex(aSwapIndex + i);
}
}
- return KErrNone;
+ // write errors are not reported at this point as this will just kill a thread unrelated to the
+ // one whose data has been lost
+ return KErrNone;
}