Change string concats to work with all OSs
[yaffs2.git] / yaffs_guts.c
index 76074cd51d8b689363a17fcb9a944f6d9af5bf0f..44eaed692cedb05ac60af308d4d4a3e999fee577 100644 (file)
@@ -11,9 +11,8 @@
  * published by the Free Software Foundation.
  */
 
-
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.72 2009-01-16 00:44:45 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.78 2009-01-27 02:52:45 charles Exp $";
 
 #include "yportenv.h"
 
@@ -34,11 +33,6 @@ const char *yaffs_guts_c_version =
 #include "yaffs_packedtags2.h"
 
 
-#ifdef CONFIG_YAFFS_WINCE
-void yfsd_LockYAFFS(BOOL fsLockOnly);
-void yfsd_UnlockYAFFS(BOOL fsLockOnly);
-#endif
-
 #define YAFFS_PASSIVE_GC_CHUNKS 2
 
 #include "yaffs_ecc.h"
@@ -752,10 +746,15 @@ static void yaffs_VerifyObject(yaffs_Object *obj)
        __u32 chunkMax;
        
        __u32 chunkIdOk;
-       __u32 chunkIsLive;
+       __u32 chunkInRange;
+       __u32 chunkShouldNotBeDeleted;
+       __u32 chunkValid; 
        
        if(!obj)
                return;
+               
+       if(obj->beingCreated)
+               return;
        
        dev = obj->myDev;
        
@@ -767,21 +766,24 @@ static void yaffs_VerifyObject(yaffs_Object *obj)
        chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
        chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
 
-       chunkIdOk = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
-       chunkIsLive = chunkIdOk &&
+       chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
+       chunkIdOk = chunkInRange || obj->hdrChunk == 0;
+       chunkValid  =  chunkInRange &&
                        yaffs_CheckChunkBit(dev,
                                            obj->hdrChunk / dev->nChunksPerBlock,
                                            obj->hdrChunk % dev->nChunksPerBlock);
+       chunkShouldNotBeDeleted = chunkInRange && !chunkValid;
+
        if(!obj->fake &&
-           (!chunkIdOk || !chunkIsLive)) {
+           (!chunkIdOk || chunkShouldNotBeDeleted)) {
           T(YAFFS_TRACE_VERIFY,
           (TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
           obj->objectId,obj->hdrChunk,
           chunkIdOk ? "" : ",out of range",
-          chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
+          chunkShouldNotBeDeleted ? ",marked as deleted" : ""));
        }
        
-       if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
+       if(chunkValid &&!yaffs_SkipNANDVerification(dev)) {
                yaffs_ExtendedTags tags;
                yaffs_ObjectHeader *oh;
                __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
@@ -1031,7 +1033,30 @@ static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
 
        yaffs_InvalidateCheckpoint(dev);
        
-       yaffs_MarkBlockBad(dev, blockInNAND);
+       if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) {
+               if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) {
+                       T(YAFFS_TRACE_ALWAYS, (TSTR(
+                               "yaffs: Failed to mark bad and erase block %d"
+                               TENDSTR), blockInNAND));
+               }
+               else {
+                       yaffs_ExtendedTags tags;
+                       int chunkId = blockInNAND * dev->nChunksPerBlock;
+
+                       __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
+
+                       memset(buffer, 0xff, dev->nDataBytesPerChunk);
+                       yaffs_InitialiseTags(&tags);
+                       tags.sequenceNumber = YAFFS_SEQUENCE_BAD_BLOCK;
+                       if (dev->writeChunkWithTagsToNAND(dev, chunkId -
+                           dev->chunkOffset, buffer, &tags) != YAFFS_OK)
+                               T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Failed to "
+                                       TCONT("write bad block marker to block %d")
+                                       TENDSTR), blockInNAND));
+
+                       yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
+               }
+       }
 
        bi->blockState = YAFFS_BLOCK_STATE_DEAD;
        bi->gcPrioritise = 0;
@@ -1115,7 +1140,6 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name)
                        bname++;
                }
        }
-       
        return sum;
 }
 
@@ -1926,6 +1950,8 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
                /* Now sweeten it up... */
 
                memset(tn, 0, sizeof(yaffs_Object));
+               tn->beingCreated = 1;
+               
                tn->myDev = dev;
                tn->hdrChunk = 0;
                tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
@@ -1947,6 +1973,8 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
                if (dev->lostNFoundDir) {
                        yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
                }
+               
+               tn->beingCreated = 0;
        }
        
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
@@ -2219,12 +2247,6 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
                theObject->yst_atime = theObject->yst_mtime =
                    theObject->yst_ctime = Y_CURRENT_TIME;
 #endif
-
-#if 0
-               theObject->sum_prev = 12345;
-               theObject->sum_trailer = 6789;
-#endif
-
                switch (type) {
                case YAFFS_OBJECT_TYPE_FILE:
                        theObject->variant.fileVariant.fileSize = 0;
@@ -3150,13 +3172,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlo
                                                 * We need to nuke the shrinkheader flags first
                                                 * We no longer want the shrinkHeader flag since its work is done
                                                 * and if it is left in place it will mess up scanning.
-                                                * Also, clear out any shadowing stuff
                                                 */
 
                                                yaffs_ObjectHeader *oh;
                                                oh = (yaffs_ObjectHeader *)buffer;
                                                oh->isShrink = 0;
-                                               tags.extraShadows = 0;
                                                tags.extraIsShrinkHeader = 0;
                                                
                                                yaffs_VerifyObjectHeader(object,oh,&tags,1);
@@ -3192,7 +3212,6 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlo
                }
 
                yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
-               
 
 
                /* Do any required cleanups */
@@ -3698,8 +3717,8 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,
        if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){
          T(YAFFS_TRACE_ERROR,
          (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
-         while(1){}
-        }
+         YBUG();
+     }
        
        
 
@@ -4299,10 +4318,18 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
                cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId;
 }
 
-static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp)
+static int yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp)
 {
 
        yaffs_Object *parent;
+
+       if (obj->variantType != cp->variantType) {
+               T(YAFFS_TRACE_ERROR,(TSTR("Checkpoint read object %d type %d "
+                       TCONT("chunk %d does not match existing object type %d")
+                       TENDSTR), cp->objectId, cp->variantType, cp->hdrChunk,
+                       obj->variantType));
+               return 0;
+       }
        
        obj->objectId = cp->objectId;
        
@@ -4314,8 +4341,16 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb
        else
                parent = NULL;
                
-       if(parent)
+       if(parent) {
+               if (parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
+                       T(YAFFS_TRACE_ALWAYS,(TSTR("Checkpoint read object %d parent %d type %d"
+                               TCONT(" chunk %d Parent type, %d, not directory")
+                               TENDSTR),
+                               cp->objectId,cp->parentId,cp->variantType,cp->hdrChunk,parent->variantType));
+                       return 0;
+               }
                yaffs_AddObjectToDirectory(parent, obj);
+       }
 
        obj->hdrChunk = cp->hdrChunk;
        obj->variantType = cp->variantType;
@@ -4335,6 +4370,7 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb
 
        if(obj->hdrChunk > 0)
                obj->lazyLoaded = 1;
+       return 1;
 }
 
 
@@ -4508,7 +4544,9 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
                else if(ok){
                        obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
                        if(obj) {
-                               yaffs_CheckpointObjectToObject(obj,&cp);
+                               ok = yaffs_CheckpointObjectToObject(obj,&cp);
+                               if (!ok)
+                                       break;
                                if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
                                         ok = yaffs_ReadCheckpointTnodes(obj);
                                 } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
@@ -4519,6 +4557,8 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
                                 }
                           
                        }
+                       else
+                               ok = 0;
                }
        }
        
@@ -4771,14 +4811,9 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
 
                                cache->locked = 1;
 
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_UnlockYAFFS(TRUE);
-#endif
+
                                memcpy(buffer, &cache->data[start], nToCopy);
 
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_LockYAFFS(TRUE);
-#endif
                                cache->locked = 0;
                        } else {
                                /* Read into the local buffer then copy..*/
@@ -4787,41 +4822,19 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
                                    yaffs_GetTempBuffer(dev, __LINE__);
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_UnlockYAFFS(TRUE);
-#endif
+
                                memcpy(buffer, &localBuffer[start], nToCopy);
 
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_LockYAFFS(TRUE);
-#endif
+
                                yaffs_ReleaseTempBuffer(dev, localBuffer,
                                                        __LINE__);
                        }
 
                } else {
-#ifdef CONFIG_YAFFS_WINCE
-                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
-
-                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
-                        * This is because we otherwise screw up WinCE's memory mapper
-                        */
-                       yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
-
-#ifdef CONFIG_YAFFS_WINCE
-                       yfsd_UnlockYAFFS(TRUE);
-#endif
-                       memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
 
-#ifdef CONFIG_YAFFS_WINCE
-                       yfsd_LockYAFFS(TRUE);
-                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
-#endif
-
-#else
                        /* A full chunk. Read directly into the supplied buffer. */
                        yaffs_ReadChunkDataFromObject(in, chunk, buffer);
-#endif
+
                }
 
                n -= nToCopy;
@@ -4860,8 +4873,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
                
                if(chunk * dev->nDataBytesPerChunk + start != offset ||
                   start >= dev->nDataBytesPerChunk){
-                  T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
-                                       (int)offset, chunk,start));
+                  T(YAFFS_TRACE_ERROR,(
+                          TSTR("AddrToChunk of offset %d gives chunk %d start %d"
+                          TENDSTR),
+                          (int)offset, chunk,start));
                }
                chunk++;
 
@@ -4933,16 +4948,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
                                if (cache) {
                                        yaffs_UseChunkCache(dev, cache, 1);
                                        cache->locked = 1;
-#ifdef CONFIG_YAFFS_WINCE
-                                       yfsd_UnlockYAFFS(TRUE);
-#endif
+
 
                                        memcpy(&cache->data[start], buffer,
                                               nToCopy);
 
-#ifdef CONFIG_YAFFS_WINCE
-                                       yfsd_LockYAFFS(TRUE);
-#endif
+
                                        cache->locked = 0;
                                        cache->nBytes = nToWriteBack;
 
@@ -4970,15 +4981,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
                                yaffs_ReadChunkDataFromObject(in, chunk,
                                                              localBuffer);
 
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_UnlockYAFFS(TRUE);
-#endif
+
 
                                memcpy(&localBuffer[start], buffer, nToCopy);
 
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_LockYAFFS(TRUE);
-#endif
                                chunkWritten =
                                    yaffs_WriteChunkDataToObject(in, chunk,
                                                                 localBuffer,
@@ -4993,30 +4999,13 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
                } else {
                        /* A full chunk. Write directly from the supplied buffer. */
                        
-#ifdef CONFIG_YAFFS_WINCE
-                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
-                        * This is because we otherwise screw up WinCE's memory mapper
-                        */
-                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
-#ifdef CONFIG_YAFFS_WINCE
-                       yfsd_UnlockYAFFS(TRUE);
-#endif
-                       memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
-#ifdef CONFIG_YAFFS_WINCE
-                       yfsd_LockYAFFS(TRUE);
-#endif
-                       chunkWritten =
-                           yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
-                                                        dev->nDataBytesPerChunk,
-                                                        0);
-                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
-#else
+
 
                        chunkWritten =
                            yaffs_WriteChunkDataToObject(in, chunk, buffer,
                                                         dev->nDataBytesPerChunk,
                                                         0);
-#endif
+
                        /* Since we've overwritten the cached data, we better invalidate it. */
                        yaffs_InvalidateChunkCache(in, chunk);
                }
@@ -5222,7 +5211,6 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
  * and the inode associated with the file.
  * It does not delete the links associated with the file.
  */
 static int yaffs_UnlinkFile(yaffs_Object * in)
 {
 
@@ -5448,6 +5436,8 @@ static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,
        obj =
            yaffs_FindOrCreateObjectByNumber(dev, objId,
                                             YAFFS_OBJECT_TYPE_FILE);
+       if (!obj)
+               return;
        yaffs_AddObjectToDirectory(dev->unlinkedDir, obj);
        obj->variant.fileVariant.shrinkSize = 0;
        obj->valid = 1;         /* So that we don't read any other info for this file */
@@ -5591,6 +5581,9 @@ static int yaffs_Scan(yaffs_Device * dev)
                bi->blockState = state;
                bi->sequenceNumber = sequenceNumber;
 
+               if(bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK)
+                       bi->blockState = state = YAFFS_BLOCK_STATE_DEAD;
+
                T(YAFFS_TRACE_SCAN_DEBUG,
                  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
                   state, sequenceNumber));
@@ -5836,7 +5829,9 @@ static int yaffs_Scan(yaffs_Device * dev)
                                            yaffs_FindOrCreateObjectByNumber
                                            (dev, oh->parentObjectId,
                                             YAFFS_OBJECT_TYPE_DIRECTORY);
-                                       if (parent->variantType ==
+                                       if(!parent)
+                                               alloc_failed = 1;
+                                       if (parent && parent->variantType ==
                                            YAFFS_OBJECT_TYPE_UNKNOWN) {
                                                 /* Set up as a directory */
                                                 parent->variantType =
@@ -5844,7 +5839,7 @@ static int yaffs_Scan(yaffs_Device * dev)
                                                 YINIT_LIST_HEAD(&parent->variant.
                                                                directoryVariant.
                                                                children);
-                                        } else if (parent->variantType !=
+                                        } else if (!parent || parent->variantType !=
                                                   YAFFS_OBJECT_TYPE_DIRECTORY)
                                        {
                                                /* Hoosterman, another problem....
@@ -6114,6 +6109,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
 
                if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
                        bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
+               if(bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK)
+                       bi->blockState = state = YAFFS_BLOCK_STATE_DEAD;
                        
                T(YAFFS_TRACE_SCAN_DEBUG,
                  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
@@ -6286,9 +6283,12 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                dev->nFreeChunks++;
                                
                        } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){
-                               printf("Error in ECC\n");
-                               /* Don't actually delete because the chunk is not yet set up as being in use */
-                               /* yaffs_DeleteChunk(dev, chunk, 1, __LINE__); */
+                               T(YAFFS_TRACE_SCAN,
+                                 (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR),
+                                 blk, c));
+
+                                 dev->nFreeChunks++;
+
                        }else if (tags.chunkId > 0) {
                                /* chunkId > 0 so it is a data chunk... */
                                unsigned int endpos;
@@ -6360,6 +6360,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                        in = yaffs_FindOrCreateObjectByNumber
                                            (dev, tags.objectId,
                                             tags.extraObjectType);
+                                       if (!in)
+                                               alloc_failed = 1;
                                }
 
                                if (!in ||
@@ -6390,8 +6392,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                                oh->isShrink = oh->inbandIsShrink;
                                        }
 
-                                       if (!in)
+                                       if (!in) {
                                                in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
+                                               if (!in)
+                                                       alloc_failed = 1;
+                                       }
 
                                }
 
@@ -6401,7 +6406,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                          (TSTR
                                           ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"
                                            TENDSTR), tags.objectId, chunk));
-
+                                       continue;
                                }
 
                                if (in->valid) {
@@ -6458,6 +6463,17 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
 
                                }
 
+                               if (!in->valid && in->variantType !=
+                                   (oh ? oh->type : tags.extraObjectType))
+                                       T(YAFFS_TRACE_ERROR, (
+                                               TSTR("yaffs tragedy: Bad object type, "
+                                           TCONT("%d != %d, for object %d at chunk ")
+                                           TCONT("%d during scan")
+                                               TENDSTR), oh ?
+                                           oh->type : tags.extraObjectType,
+                                           in->variantType, tags.objectId,
+                                           chunk));
+
                                if (!in->valid &&
                                    (tags.objectId == YAFFS_OBJECTID_ROOT ||
                                     tags.objectId ==
@@ -6550,11 +6566,14 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                        }
                                        in->dirty = 0;
 
+                                       if (!parent)
+                                               alloc_failed = 1;
+
                                        /* directory stuff...
                                         * hook up to parent
                                         */
 
-                                       if (parent->variantType ==
+                                       if (parent && parent->variantType ==
                                            YAFFS_OBJECT_TYPE_UNKNOWN) {
                                                 /* Set up as a directory */
                                                 parent->variantType =
@@ -6562,7 +6581,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)
                                                 YINIT_LIST_HEAD(&parent->variant.
                                                                directoryVariant.
                                                                children);
-                                        } else if (parent->variantType !=
+                                        } else if (!parent || parent->variantType !=
                                                   YAFFS_OBJECT_TYPE_DIRECTORY)
                                        {
                                                /* Hoosterman, another problem....