From e434bac0480bf62ea4d66519ff40dad3d2e3e410 Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 13 Oct 2006 08:52:49 +0000 Subject: [PATCH] Tweaks to retirement handling --- direct/dtest.c | 2 +- direct/yaffs_fileem2k.c | 21 ++++++++++++++++++++- direct/yaffs_fileem2k.h | 4 ++-- direct/yaffscfg2k.c | 1 + yaffs_guts.c | 38 +++++++++++++++++++++++++++++--------- yaffs_guts.h | 10 +++++++--- yaffs_nand.c | 5 ++--- 7 files changed, 62 insertions(+), 19 deletions(-) diff --git a/direct/dtest.c b/direct/dtest.c index 2bd26e5..07c8059 100644 --- 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); diff --git a/direct/yaffs_fileem2k.c b/direct/yaffs_fileem2k.c index dcb3e5f..59d0c8e 100644 --- a/direct/yaffs_fileem2k.c +++ b/direct/yaffs_fileem2k.c @@ -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)); diff --git a/direct/yaffs_fileem2k.h b/direct/yaffs_fileem2k.h index aa8f661..5b24ef2 100644 --- 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) diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c index bf4f172..cb960bc 100644 --- a/direct/yaffscfg2k.c +++ b/direct/yaffscfg2k.c @@ -14,6 +14,7 @@ #include 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) diff --git a/yaffs_guts.c b/yaffs_guts.c index 306b9b4..7b41a76 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -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; } diff --git a/yaffs_guts.h b/yaffs_guts.h index cb9a8e0..543bf62 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -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 diff --git a/yaffs_nand.c b/yaffs_nand.c index 26acf20..8c4f639 100644 --- a/yaffs_nand.c +++ b/yaffs_nand.c @@ -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; -- 2.30.2