normalise licence headers
[yaffs2.git] / yaffs_guts.c
index 7b41a764941972cefd61949ccf499bb478b91d2a..f88851eea5c89e971120c6267b6a7e012f1bebe9 100644 (file)
@@ -13,7 +13,7 @@
  */
 
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.40 2006-10-13 08:52:49 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.45 2006-11-14 03:07:17 charles Exp $";
 
 #include "yportenv.h"
 
@@ -484,13 +484,15 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
  
 static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
 {
+       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
 
        yaffs_InvalidateCheckpoint(dev);
        
        yaffs_MarkBlockBad(dev, blockInNAND);
 
-       yaffs_GetBlockInfo(dev, blockInNAND)->blockState =
-           YAFFS_BLOCK_STATE_DEAD;
+       bi->blockState = YAFFS_BLOCK_STATE_DEAD;
+       bi->gcPrioritise = 0;
+       bi->needsRetiring = 0;
 
        dev->nRetiredBlocks++;
 }
@@ -527,6 +529,21 @@ void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi)
        }
 }
 
+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)
 {
 
@@ -539,6 +556,9 @@ static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int
        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));
+
                
        }
        
@@ -1937,7 +1957,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);
@@ -2010,8 +2030,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)
@@ -2038,15 +2056,15 @@ static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,
                for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
 
                        bi = yaffs_GetBlockInfo(dev, i);
-                       if(bi->gcPrioritise)
+                       if(bi->gcPrioritise) {
                                pendingPrioritisedExist = 1;
-                       if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
-                          bi->gcPrioritise &&
-                          yaffs_BlockNotDisqualifiedFromGC(dev, bi)){
-                               pagesInUse = (bi->pagesInUse - bi->softDeletions);
-                               dirtiest = i;
-                               prioritised = 1;
-                               aggressive = 1; /* Fool the non-aggressive skip logiv below */
+                               if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
+                                  yaffs_BlockNotDisqualifiedFromGC(dev, bi)){
+                                       pagesInUse = (bi->pagesInUse - bi->softDeletions);
+                                       dirtiest = i;
+                                       prioritised = 1;
+                                       aggressive = 1; /* Fool the non-aggressive skip logiv below */
+                               }
                        }
                }
                
@@ -2138,6 +2156,11 @@ static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo)
        /* If the block is still healthy erase it and mark as clean.
         * If the block has had a data failure, then retire it.
         */
+        
+       T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
+               (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
+               blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
+               
        bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
 
        if (!bi->needsRetiring) {
@@ -3712,7 +3735,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){
@@ -3751,9 +3778,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) {
@@ -3845,6 +3872,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)
@@ -3864,6 +3892,8 @@ int yaffs_CheckpointRestore(yaffs_Device *dev)
 
        T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
        
+       yaffs_ReportOddballBlocks(dev);
+       
        return retval;
 }
 
@@ -5141,6 +5171,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__);
@@ -5384,39 +5420,41 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                        state = YAFFS_BLOCK_STATE_EMPTY;
                                        dev->nErasedBlocks++;
                                } else {
-                                       /* this is the block being allocated from */
-                                       if (state ==
-                                           YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
-                                               T(YAFFS_TRACE_SCAN,
-                                                 (TSTR
-                                                  (" Allocating from %d %d"
-                                                   TENDSTR), blk, c));
+                                       if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
+                                           state == YAFFS_BLOCK_STATE_ALLOCATING) {
+                                               if(dev->sequenceNumber == bi->sequenceNumber) {
+                                                       /* this is the block being allocated from */
+                                               
+                                                       T(YAFFS_TRACE_SCAN,
+                                                         (TSTR
+                                                          (" Allocating from %d %d"
+                                                           TENDSTR), blk, c));
+
+                                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
+                                                       dev->allocationBlock = blk;
+                                                       dev->allocationPage = c;
+                                                       dev->allocationBlockFinder = blk;       
+                                               }
+                                               else {
+                                                       /* This is a partially written block that is not
+                                                        * the current allocation block. This block must have
+                                                        * had a write failure, so set up for retirement.
+                                                        */
+                                                 
+                                                        bi->needsRetiring = 1;
+                                                        bi->gcPrioritise = 1;
+                                                                                                        
+                                                        T(YAFFS_TRACE_ALWAYS,
+                                                        (TSTR("Partially written block %d being set for retirement" TENDSTR),
+                                                        blk));
+                                               }
+
                                        }
-                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
-                                       dev->allocationBlock = blk;
-                                       dev->allocationPage = c;
-                                       dev->allocationBlockFinder = blk;       
-                                       /* Set it to here to encourage the allocator to 
-                                        *  go forth from here.
-                                        */
                                         
-                                       /* Yaffs2 sanity check:
-                                        * This should be the one with the highest sequence number
-                                        */
-                                       if (dev->isYaffs2
-                                           && (dev->sequenceNumber !=
-                                               bi->sequenceNumber)) {
-                                               T(YAFFS_TRACE_ALWAYS,
-                                                 (TSTR
-                                                  ("yaffs: Allocation block %d was not highest sequence "
-                                                   "id: block seq = %d, dev seq = %d"
-                                                   TENDSTR), blk,
-                                                  bi->sequenceNumber,
-                                                  dev->sequenceNumber));
-                                       }
                                }
 
                                dev->nFreeChunks++;
+                               
                        } else if (tags.chunkId > 0) {
                                /* chunkId > 0 so it is a data chunk... */
                                unsigned int endpos;