Tweaks to retirement handling
authorcharles <charles>
Fri, 13 Oct 2006 08:52:49 +0000 (08:52 +0000)
committercharles <charles>
Fri, 13 Oct 2006 08:52:49 +0000 (08:52 +0000)
direct/dtest.c
direct/yaffs_fileem2k.c
direct/yaffs_fileem2k.h
direct/yaffscfg2k.c
yaffs_guts.c
yaffs_guts.h
yaffs_nand.c

index 2bd26e5..07c8059 100644 (file)
@@ -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);
 
 
 
index dcb3e5f..59d0c8e 100644 (file)
@@ -15,7 +15,7 @@
 // This provides a YAFFS nand emulation on a file for emulating 2kB pages.
 // THis is only intended as test code to test persistence etc.
 
-const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.6 2006-10-03 10:13:03 charles Exp $";
+const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.7 2006-10-13 08:52:49 charles Exp $";
 
 
 #include "yportenv.h"
@@ -204,6 +204,9 @@ int yaffs_CheckAllFF(const __u8 *ptr, int n)
 }
 
 
+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(yaffs_Device *dev,int chunkInNAND, __u8 *da
                        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 *dev, int blockNumber)
                
        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));
index aa8f661..5b24ef2 100644 (file)
@@ -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)
index bf4f172..cb960bc 100644 (file)
@@ -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)
index 306b9b4..7b41a76 100644 (file)
@@ -13,7 +13,7 @@
  */
 
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.39 2006-10-03 10:13:03 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.40 2006-10-13 08:52:49 charles Exp $";
 
 #include "yportenv.h"
 
@@ -511,19 +511,35 @@ static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
 {
 }
 
+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_FindBlockForGarbageCollection(yaffs_Device * dev,
        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_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
        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_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
        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;
 }
index cb9a8e0..543bf62 100644 (file)
@@ -14,7 +14,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
- * $Id: yaffs_guts.h,v 1.24 2006-10-03 10:13:03 charles Exp $
+ * $Id: yaffs_guts.h,v 1.25 2006-10-13 08:52:49 charles Exp $
  */
 
 #ifndef __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
index 26acf20..8c4f639 100644 (file)
@@ -13,7 +13,7 @@
  */
  
 const char *yaffs_nand_c_version =
-    "$Id: yaffs_nand.c,v 1.3 2006-10-03 10:13:03 charles Exp $";
+    "$Id: yaffs_nand.c,v 1.4 2006-10-13 08:52:49 charles Exp $";
 
 #include "yaffs_nand.h"
 #include "yaffs_tagscompat.h"
@@ -45,8 +45,7 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
           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;