diff -r a77889bee936 -r 647ab20fee2e kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp --- 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; }