diff yaffs_guts.c @ 185:fa4e74c5013d

Rolling in Ians and other changes
author charles
date Wed, 18 Jul 2007 20:40:38 +0100
parents ebfd69da1173
children f9265a4a9545
line wrap: on
line diff
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -920,86 +920,88 @@ static int yaffs_WriteNewChunkWithTagsTo
 					     yaffs_ExtendedTags * tags,
 					     int useReserve)
 {
-	int chunk;
-
+	int attempts = 0;
 	int writeOk = 0;
-	int erasedOk = 1;
-	int attempts = 0;
-	yaffs_BlockInfo *bi;
-	
+	int chunk;
+
 	yaffs_InvalidateCheckpoint(dev);
 
 	do {
-		chunk = yaffs_AllocateChunk(dev, useReserve,&bi);
-
-		if (chunk >= 0) {
-			/* First check this chunk is erased, if it needs checking.
-			 * The checking policy (unless forced always on) is as follows:
-			 * Check the first page we try to write in a block.
-			 * - If the check passes then we don't need to check any more.
-			 * - If the check fails, we check again...
-			 * If the block has been erased, we don't need to check.
-			 *
-			 * However, if the block has been prioritised for gc, then
-			 * we think there might be something odd about this block
-			 * and stop using it.
-			 *
-			 * Rationale:
-			 * We should only ever see chunks that have not been erased
-			 * if there was a partially written chunk due to power loss
-			 * This checking policy should catch that case with very
-			 * few checks and thus save a lot of checks that are most likely not
-			 * needed.
-			 */
-			 
-			 if(bi->gcPrioritise){
-			 		yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
-			} else {
+		yaffs_BlockInfo *bi = 0;
+		int erasedOk = 0;
+
+		chunk = yaffs_AllocateChunk(dev, useReserve, &bi);
+		if (chunk < 0) {
+			/* no space */
+			break;
+		}
+
+		/* First check this chunk is erased, if it needs
+		 * checking.  The checking policy (unless forced
+		 * always on) is as follows:
+		 *
+		 * Check the first page we try to write in a block.
+		 * If the check passes then we don't need to check any
+		 * more.	If the check fails, we check again...
+		 * If the block has been erased, we don't need to check.
+		 *
+		 * However, if the block has been prioritised for gc,
+		 * then we think there might be something odd about
+		 * this block and stop using it.
+		 *
+		 * Rationale: We should only ever see chunks that have
+		 * not been erased if there was a partially written
+		 * chunk due to power loss.  This checking policy should
+		 * catch that case with very few checks and thus save a
+		 * lot of checks that are most likely not needed.
+		 */
+		if (bi->gcPrioritise) {
+			yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
+			/* try another chunk */
+			continue;
+		}
+
+		/* let's give it a try */
+		attempts++;
+
 #ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
-
-				bi->skipErasedCheck = 0;
-
+		bi->skipErasedCheck = 0;
 #endif
-				if(!bi->skipErasedCheck){
-					erasedOk = yaffs_CheckChunkErased(dev, chunk);
-					if(erasedOk && !bi->gcPrioritise)
-						bi->skipErasedCheck = 1;
-				}
-
-				if (!erasedOk) {
-					T(YAFFS_TRACE_ERROR,
-					  (TSTR
-					   ("**>> yaffs chunk %d was not erased"
-					    TENDSTR), chunk));
-				} else {
-					writeOk =
-					    yaffs_WriteChunkWithTagsToNAND(dev, chunk,
-									   data, tags);
-				}
-			
-				attempts++;
-
-				if (writeOk) {
-					/*
-					 *  Copy the data into the robustification buffer.
-					 *  NB We do this at the end to prevent duplicates in the case of a write error.
-					 *  Todo
-					 */
-					yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
-				
-				} else {
-					/* The erased check or write failed */
-					yaffs_HandleWriteChunkError(dev, chunk, erasedOk);
-				}
+		if (!bi->skipErasedCheck) {
+			erasedOk = yaffs_CheckChunkErased(dev, chunk);
+			if (erasedOk != YAFFS_OK) {
+				T(YAFFS_TRACE_ERROR,
+				(TSTR ("**>> yaffs chunk %d was not erased"
+				TENDSTR), chunk));
+
+				/* try another chunk */
+				continue;
 			}
+			bi->skipErasedCheck = 1;
 		}
 
-	} while (chunk >= 0 && !writeOk);
+		writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk,
+				data, tags);
+		if (writeOk != YAFFS_OK) {
+			yaffs_HandleWriteChunkError(dev, chunk, erasedOk);
+			/* try another chunk */
+			continue;
+		}
+
+		/* Copy the data into the robustification buffer */
+		yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
+
+	} while (writeOk != YAFFS_OK && 
+	        (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
+	
+	if(!writeOk)
+		chunk = -1;
 
 	if (attempts > 1) {
 		T(YAFFS_TRACE_ERROR,
-		  (TSTR("**>> yaffs write required %d attempts" TENDSTR),
-		   attempts));
+			(TSTR("**>> yaffs write required %d attempts" TENDSTR),
+			attempts));
+
 		dev->nRetriedWrites += (attempts - 1);
 	}
 
@@ -2591,7 +2593,6 @@ static int yaffs_FindBlockForGarbageColl
 	int pagesInUse = 0;
 	int prioritised=0;
 	yaffs_BlockInfo *bi;
-	static int nonAggressiveSkip = 0;
 	int pendingPrioritisedExist = 0;
 	
 	/* First let's see if we need to grab a prioritised block */
@@ -2623,9 +2624,9 @@ static int yaffs_FindBlockForGarbageColl
 	 * block has only a few pages in use.
 	 */
 
-	nonAggressiveSkip--;
-
-	if (!aggressive && (nonAggressiveSkip > 0)) {
+	dev->nonAggressiveSkip--;
+
+	if (!aggressive && (dev->nonAggressiveSkip > 0)) {
 		return -1;
 	}
 
@@ -2686,7 +2687,7 @@ static int yaffs_FindBlockForGarbageColl
 	dev->oldestDirtySequence = 0;
 
 	if (dirtiest > 0) {
-		nonAggressiveSkip = 4;
+		dev->nonAggressiveSkip = 4;
 	}
 
 	return dirtiest;