//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);
// 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"
}
+static int fail300 = 1;
+static int fail320 = 1;
+
int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
{
int nread;
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;
}
}
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 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)
#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)
*/
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"
{
}
+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 */
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;
}
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))?
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;
}
*
* 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__
#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
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 */
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
*/
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"
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;