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 2bd26e5d6bba5263d2ba3168bba7835a6474a4ef..07c80598c72c6e6ab4bf5031fee5f8c6fe47647a 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);
         //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 dcb3e5fc7e85a73c1f6b28473f2987bb9a3e9723..59d0c8efa12e3d51b1faf283bb6cdb8dcbec6ca2 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.
 
 // 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"
 
 
 #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;
 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);
                        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;
                }
        }
                        if(nread != sizeof(pt)) return YAFFS_FAIL;
                }
        }
@@ -288,6 +304,9 @@ int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
                
        CheckInit();
        
                
        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));
        if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
        {
                T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
index aa8f661ce7cdb60dc5823cb7e9afe2853edb4e58..5b24ef2f9eae73426124deb5ad87cc417af65c69 100644 (file)
@@ -17,8 +17,8 @@
 
 #if 1
 
 
 #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)
 #define PAGE_DATA_SIZE (2048)
 #define PAGE_SPARE_SIZE  (64)
 #define PAGE_SIZE  (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
index bf4f1721d38d713879a5ba12a1cc57d8e5acd213..cb960bcf7796686d90bb8289503b6a9844116e2b 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;
 #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)
 
 
 void yaffsfs_SetError(int err)
index 306b9b4bb08b4c688c5df0ff455c8836fd0bd06c..7b41a764941972cefd61949ccf499bb478b91d2a 100644 (file)
@@ -13,7 +13,7 @@
  */
 
 const char *yaffs_guts_c_version =
  */
 
 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"
 
 
 #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);
 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  */
                /* Was an actual write failure, so mark the block for retirement  */
-
                bi->needsRetiring = 1;
                bi->needsRetiring = 1;
+               
        }
        
        /* Delete the chunk */
        }
        
        /* 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 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);
        
        /* 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);
                        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 */
                        }
                }
                                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;
        }
 
                        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;
        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))?
        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) &&
        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;
 }
                     (cp.head == ((head) ? 1 : 0));
        return ok ? 1 : 0;
 }
index cb9a8e09bce4d11beb29530ff6421ea455b5bae2..543bf628c77f91bfe3b8d7086183c1054a336279 100644 (file)
@@ -14,7 +14,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
  *
  * 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__
  */
 
 #ifndef __YAFFS_GUTS_H__
@@ -69,6 +69,8 @@
 
 #define YAFFS_NCHECKPOINT_OBJECTS      5000
 
 
 #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
 #ifdef CONFIG_YAFFS_UNICODE
 #define YAFFS_MAX_NAME_LENGTH          127
 #define YAFFS_MAX_ALIAS_LENGTH         79
@@ -268,14 +270,15 @@ typedef enum {
 
 typedef struct {
 
 
 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 */
        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 */
 
 #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_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
 
 #endif
index 26acf201d76cfd2e6ee09795328b87b45b47d873..8c4f639a481e0d929c021af1db5bd0dbfba52e0a 100644 (file)
@@ -13,7 +13,7 @@
  */
  
 const char *yaffs_nand_c_version =
  */
  
 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"
 
 #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);
           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;
        }
                                                                
        return result;