X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=a5e8f670a03fd48b30bb40ac37587aedf5d3efd5;hp=306b9b4bb08b4c688c5df0ff455c8836fd0bd06c;hb=5dcdf77ef2af74d01edb41d8eadee55176c33cad;hpb=378bbdf4d64b8b26db55a495ab6ae520ff62e471 diff --git a/yaffs_guts.c b/yaffs_guts.c index 306b9b4..a5e8f67 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.42 2006-11-08 00:33:29 charles Exp $"; #include "yportenv.h" @@ -511,19 +511,53 @@ 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_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 */ @@ -1921,7 +1955,7 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev) 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); @@ -1994,8 +2028,6 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev, */ return (bi->sequenceNumber <= dev->oldestDirtySequence); - return 1; - } /* FindDiretiestBlock is used to select the dirtiest block (or close enough) @@ -2015,22 +2047,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 +3444,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 +3461,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; } @@ -3692,7 +3728,11 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) 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){ @@ -3731,9 +3771,9 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) 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) { @@ -3825,6 +3865,7 @@ static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) int yaffs_CheckpointSave(yaffs_Device *dev) { + yaffs_ReportOddballBlocks(dev); T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); if(!dev->isCheckpointed) @@ -3844,6 +3885,8 @@ int yaffs_CheckpointRestore(yaffs_Device *dev) T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); + yaffs_ReportOddballBlocks(dev); + return retval; } @@ -5121,6 +5164,12 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) 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__);