*/
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.42 2006-11-08 00:33:29 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_ReportOddballBlocks(yaffs_Device *dev)
+{
+ int i;
+
+ for(i = dev->internalStartBlock; i <= dev->internalEndBlock && (yaffs_traceMask & YAFFS_TRACE_BAD_BLOCKS); i++){
+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
+ if(bi->needsRetiring || bi->gcPrioritise)
+ T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("yaffs block %d%s%s" TENDSTR),
+ i,
+ bi->needsRetiring ? " needs retiring" : "",
+ bi->gcPrioritise ? " gc prioritised" : ""));
+
+ }
+}
+
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;
+ T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
+
+
}
/* Delete the chunk */
dev->blockInfoAlt = 0;
/* Set up dynamic blockinfo stuff. */
- dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; // round up bytes
+ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
if(!dev->chunkBits){
dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);
*/
return (bi->sequenceNumber <= dev->oldestDirtySequence);
- return 1;
-
}
/* FindDiretiestBlock is used to select the dirtiest block (or close enough)
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;
}
if (!obj->deferedFree) {
yaffs_ObjectToCheckpointObject(&cp,obj);
cp.structType = sizeof(cp);
- /* printf("Write out object %d type %d\n",obj->objectId,obj->variantType); */
+
+ T(YAFFS_TRACE_CHECKPOINT,(
+ TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
+ cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
+
ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
if(ok && cp.objectId == ~0)
done = 1;
else if(ok){
- T(YAFFS_TRACE_CHECKPOINT,(TSTR("Read object %d parent %d type %d" TENDSTR),
- cp.objectId,cp.parentId,cp.variantType));
obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
+ cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
if(obj) {
yaffs_CheckpointObjectToObject(obj,&cp);
if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
int yaffs_CheckpointSave(yaffs_Device *dev)
{
+ yaffs_ReportOddballBlocks(dev);
T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
if(!dev->isCheckpointed)
T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+ yaffs_ReportOddballBlocks(dev);
+
return retval;
}
yaffs_ExtendedTags tags;
int result;
+#if 0
+ T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
+ in->objectId,
+ in->lazyLoaded ? "not yet" : "already"));
+#endif
+
if(in->lazyLoaded){
in->lazyLoaded = 0;
chunkData = yaffs_GetTempBuffer(dev, __LINE__);