changeset 153:0e41be657b37

Tweaks to retirement handling
author charles
date Fri, 13 Oct 2006 09:52:49 +0100
parents 3bc7020d669c
children 45c7c841574a
files direct/dtest.c direct/yaffs_fileem2k.c direct/yaffs_fileem2k.h direct/yaffscfg2k.c yaffs_guts.c yaffs_guts.h yaffs_nand.c
diffstat 7 files changed, 58 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/direct/dtest.c
+++ b/direct/dtest.c
@@ -1970,7 +1970,7 @@ int main(int argc, char *argv[])
 	 //multi_mount_test("/flash/flash",20);
 	 //checkpoint_fill_test("/flash/flash",20);
 	 //checkpoint_upgrade_test("/flash/flash",20);
-	  huge_array_test("/flash/flash",2);
+	  huge_array_test("/flash/flash",10);
 
 
 
--- a/direct/yaffs_fileem2k.c
+++ b/direct/yaffs_fileem2k.c
@@ -204,6 +204,9 @@ int yaffs_CheckAllFF(const __u8 *ptr, in
 }
 
 
+static int fail300 = 1;
+static int fail320 = 1;
+
 int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
 {
 	int nread;
@@ -249,6 +252,19 @@ int yflash_ReadChunkWithTagsFromNAND(yaf
 			yaffs_PackedTags2 pt;
 			nread= read(h,&pt,sizeof(pt));
 			yaffs_UnpackTags2(tags,&pt);
+			if((chunkInNAND >> 6) == 300) {
+			    if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+			       tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+			       fail300 = 0;
+			    }
+			    
+			}
+			if((chunkInNAND >> 6) == 320) {
+			    if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
+			       tags->eccResult = YAFFS_ECC_RESULT_FIXED;
+			       fail320 = 0;
+			    }
+			}
 			if(nread != sizeof(pt)) return YAFFS_FAIL;
 		}
 	}
@@ -288,6 +304,9 @@ int yflash_EraseBlockInNAND(yaffs_Device
 		
 	CheckInit();
 	
+	if(blockNumber == 320)
+		fail320 = 1;
+	
 	if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
 	{
 		T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
--- a/direct/yaffs_fileem2k.h
+++ b/direct/yaffs_fileem2k.h
@@ -17,8 +17,8 @@
 
 #if 1
 
-//#define SIZE_IN_MB 128
-#define SIZE_IN_MB 8000
+#define SIZE_IN_MB 128
+//#define SIZE_IN_MB 8000
 #define PAGE_DATA_SIZE (2048)
 #define PAGE_SPARE_SIZE  (64)
 #define PAGE_SIZE  (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
--- a/direct/yaffscfg2k.c
+++ b/direct/yaffscfg2k.c
@@ -14,6 +14,7 @@
 #include <errno.h>
 
 unsigned yaffs_traceMask = YAFFS_TRACE_SCAN |  YAFFS_TRACE_GC /*| YAFFS_TRACE_GC_DETAIL | YAFFS_TRACE_WRITE */ | YAFFS_TRACE_ERASE | YAFFS_TRACE_TRACING | YAFFS_TRACE_ALLOCATE | YAFFS_TRACE_CHECKPOINT;
+//unsigned yaffs_traceMask = ~0;
 
 
 void yaffsfs_SetError(int err)
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -511,19 +511,35 @@ static void yaffs_HandleUpdateChunk(yaff
 {
 }
 
+void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi)
+{
+	if(!bi->gcPrioritise){
+		bi->gcPrioritise = 1;
+		dev->hasPendingPrioritisedGCs = 1;
+		bi->chunkErrorStrikes ++;
+		
+		if(bi->chunkErrorStrikes > 3){
+			bi->needsRetiring = 1; /* Too many stikes, so retire this */
+			T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
+
+		}
+		
+	}
+}
+
 static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk)
 {
 
 	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
 	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
+
+	yaffs_HandleChunkError(dev,bi);
 		
-	bi->gcPrioritise = 1;
-	dev->hasPendingPrioritisedGCs = 1;
 	
-	if(erasedOk) {
+	if(erasedOk ) {
 		/* Was an actual write failure, so mark the block for retirement  */
-
 		bi->needsRetiring = 1;
+		
 	}
 	
 	/* Delete the chunk */
@@ -2015,22 +2031,26 @@ static int yaffs_FindBlockForGarbageColl
 	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 */
 	if(dev->hasPendingPrioritisedGCs){
 		for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
 
 			bi = yaffs_GetBlockInfo(dev, i);
+			if(bi->gcPrioritise)
+				pendingPrioritisedExist = 1;
 			if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
 			   bi->gcPrioritise &&
 			   yaffs_BlockNotDisqualifiedFromGC(dev, bi)){
 				pagesInUse = (bi->pagesInUse - bi->softDeletions);
-				dirtiest = b;
+				dirtiest = i;
 				prioritised = 1;
 				aggressive = 1; /* Fool the non-aggressive skip logiv below */
 			}
 		}
-		if(dirtiest < 0) /* None found, so we can clear this */
+		
+		if(!pendingPrioritisedExist) /* None found, so we can clear this */
 			dev->hasPendingPrioritisedGCs = 0;
 	}
 
@@ -3408,7 +3428,7 @@ static int yaffs_WriteCheckpointValidity
 	yaffs_CheckpointValidity cp;
 	cp.structType = sizeof(cp);
 	cp.magic = YAFFS_MAGIC;
-	cp.version = 1;
+	cp.version = YAFFS_CHECKPOINT_VERSION;
 	cp.head = (head) ? 1 : 0;
 	
 	return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
@@ -3425,7 +3445,7 @@ static int yaffs_ReadCheckpointValidityM
 	if(ok)
 		ok = (cp.structType == sizeof(cp)) &&
 		     (cp.magic == YAFFS_MAGIC) &&
-		     (cp.version == 1) &&
+		     (cp.version == YAFFS_CHECKPOINT_VERSION) &&
 		     (cp.head == ((head) ? 1 : 0));
 	return ok ? 1 : 0;
 }
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -69,6 +69,8 @@
 
 #define YAFFS_NCHECKPOINT_OBJECTS	5000
 
+#define YAFFS_CHECKPOINT_VERSION 	2
+
 #ifdef CONFIG_YAFFS_UNICODE
 #define YAFFS_MAX_NAME_LENGTH		127
 #define YAFFS_MAX_ALIAS_LENGTH		79
@@ -268,14 +270,15 @@ typedef enum {
 
 typedef struct {
 
-	int softDeletions:12;	/* number of soft deleted pages */
-	int pagesInUse:12;	/* number of pages in use */
+	int softDeletions:10;	/* number of soft deleted pages */
+	int pagesInUse:10;	/* number of pages in use */
 	yaffs_BlockState blockState:4;	/* One of the above block states */
 	__u32 needsRetiring:1;	/* Data has failed on this block, need to get valid data off */
                         	/* and retire the block. */
 	__u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
 	__u32 gcPrioritise: 1; 	/* An ECC check or bank check has failed on this block. 
 				   It should be prioritised for GC */
+        __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
 
 #ifdef CONFIG_YAFFS_YAFFS2
 	__u32 hasShrinkHeader:1; /* This block has at least one shrink object header */
@@ -885,5 +888,6 @@ void yaffs_GutsTest(yaffs_Device * dev);
 void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
 void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn);
 int yaffs_CheckFF(__u8 * buffer, int nBytes);
+void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
 
 #endif
--- a/yaffs_nand.c
+++ b/yaffs_nand.c
@@ -45,8 +45,7 @@ int yaffs_ReadChunkWithTagsFromNAND(yaff
 	   tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){
 	
 		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
-		bi->gcPrioritise = 1;
-		dev->hasPendingPrioritisedGCs = 1;
+                yaffs_HandleChunkError(dev,bi);
 	}
 								
 	return result;