kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp
changeset 245 647ab20fee2e
parent 176 af6ec97d9189
--- 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;  
 	}