*** empty log message ***
[yaffs/.git] / yaffs_guts.c
index abb01e2c1694ede4e0be49e82b7c9e564c560029..fa1c9d59d1645a4c7953827ea7105750da19a155 100644 (file)
@@ -73,7 +73,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn
 \r
 static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type);\r
 static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj);\r
-static int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name);\r
+static int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force);\r
 static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId);\r
 static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);\r
 static int yaffs_CheckStructures(void);\r
@@ -87,6 +87,7 @@ static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaf
 \r
 static int  yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND);\r
 \r
+static int yaffs_UnlinkWorker(yaffs_Object *obj);\r
 \r
 \r
 static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1);\r
@@ -187,7 +188,6 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8
 \r
 static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND)\r
 {\r
-#if 1\r
 \r
        static int init = 0;\r
        static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];\r
@@ -208,7 +208,6 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND
        if(memcmp(cmpbuf,data,YAFFS_BYTES_PER_CHUNK)) return  YAFFS_FAIL;\r
        if(memcmp(cmpbuf,spare,16)) return YAFFS_FAIL;\r
 \r
-#endif\r
        \r
        return YAFFS_OK;\r
        \r
@@ -244,9 +243,14 @@ static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8
                {\r
 \r
                        // First check this chunk is erased...\r
+#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK\r
                        writeOk = yaffs_CheckChunkErased(dev,chunk);\r
-               \r
-                       if(writeOk)\r
+#endif         \r
+                       if(!writeOk)\r
+                       {\r
+                               T((TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk));\r
+                       }\r
+                       else\r
                        {\r
                                writeOk =  yaffs_WriteChunkToNAND(dev,chunk,data,spare);\r
                        }\r
@@ -260,14 +264,15 @@ static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8
                                // NB We check a raw read without ECC correction applied\r
                                yaffs_ReadChunkFromNAND(dev,chunk,rbData,&rbSpare,0);\r
                                \r
+#ifndef CONFIG_YAFFS_DISABLE_WRITE_VERIFY\r
                                if(!yaffs_VerifyCompare(data,rbData,spare,&rbSpare))\r
                                                        {\r
                                        // Didn't verify\r
-                                       T((TSTR("**>> yaffs write failed on chunk %d" TENDSTR), chunk));\r
-                                       // yaffs_DeleteChunk(dev,chunk);\r
+                                       T((TSTR("**>> yaffs write verify failed on chunk %d" TENDSTR), chunk));\r
 \r
                                        writeOk = 0;\r
-                               }                                       \r
+                               }       \r
+#endif                         \r
                                \r
                        }\r
                        if(writeOk)\r
@@ -327,12 +332,19 @@ static int yaffs_RewriteBufferedBlock(yaffs_Device *dev)
        //      Set current write block to the new block\r
        \r
        dev->doingBufferedBlockRewrite = 0;\r
+       \r
+       return 1;\r
 }\r
 \r
 \r
 static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND)\r
 {\r
-       \r
+       int blockInNAND = chunkInNAND/YAFFS_CHUNKS_PER_BLOCK;\r
+\r
+       // Mark the block for retirement\r
+       dev->blockInfo[blockInNAND].needsRetiring = 1;\r
+\r
+       //TODO  \r
        // Just do a garbage collection on the affected block then retire the block\r
        // NB recursion\r
 }\r
@@ -352,6 +364,12 @@ static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaf
 \r
 static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND)\r
 {\r
+       int blockInNAND = chunkInNAND/YAFFS_CHUNKS_PER_BLOCK;\r
+\r
+       // Mark the block for retirement\r
+       dev->blockInfo[blockInNAND].needsRetiring = 1;\r
+       // Delete the chunk\r
+       yaffs_DeleteChunk(dev,chunkInNAND);\r
 }\r
 \r
 \r
@@ -360,6 +378,7 @@ static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND)
 static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1)\r
 {\r
 \r
+\r
        if( memcmp(d0,d1,YAFFS_BYTES_PER_CHUNK) != 0 ||\r
                s0->tagByte0 != s1->tagByte0 ||\r
                s0->tagByte1 != s1->tagByte1 ||\r
@@ -1411,7 +1430,7 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,
                                break;\r
                }\r
 \r
-               if(yaffs_UpdateObjectHeader(in,name) < 0)\r
+               if(yaffs_UpdateObjectHeader(in,name,0) < 0)\r
                {\r
                        // Could not create the object header, fail the creation\r
                        yaffs_UnlinkWorker(in);\r
@@ -1479,7 +1498,7 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const
                obj->dirty = 1;\r
                yaffs_AddObjectToDirectory(newDir,obj);\r
                \r
-               if(yaffs_UpdateObjectHeader(obj,newName) >= 0)\r
+               if(yaffs_UpdateObjectHeader(obj,newName,0) >= 0)\r
                {\r
                        return YAFFS_OK;\r
                }\r
@@ -1638,21 +1657,52 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev)
 }\r
 \r
 \r
-static int yaffs_FindBlockForAllocation(yaffs_Device *dev,int useReserve)\r
+static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo)\r
+{\r
+       yaffs_BlockInfo *bi = &dev->blockInfo[blockNo];\r
+       \r
+       int erasedOk = 0;\r
+       \r
+       // If the block is still healthy erase it and mark as clean.\r
+       // If the block has had a data failure, then retire it.\r
+       bi->blockState = YAFFS_BLOCK_STATE_DIRTY;\r
+\r
+       if(!bi->needsRetiring)\r
+       {\r
+               erasedOk = yaffs_EraseBlockInNAND(dev,blockNo);\r
+               if(!erasedOk)\r
+               {\r
+                       T((TSTR("**>> Erasure failed %d" TENDSTR),blockNo));\r
+               }\r
+       }\r
+       \r
+       if( erasedOk )\r
+       {\r
+               bi->blockState = YAFFS_BLOCK_STATE_EMPTY;\r
+               dev->nErasedBlocks++;\r
+               bi->pagesInUse = 0;\r
+               bi->pageBits = 0;\r
+       \r
+               T((TSTR("Erased block %d" TENDSTR),blockNo));\r
+       }\r
+       else\r
+       {\r
+               yaffs_RetireBlock(dev,blockNo);\r
+               T((TSTR("**>> Block %d retired" TENDSTR),blockNo));\r
+       }\r
+}\r
+\r
+\r
+static int yaffs_FindBlockForAllocation(yaffs_Device *dev)\r
 {\r
        int i;\r
        \r
-       if(useReserve && dev->nErasedBlocks < 1)\r
+       if(dev->nErasedBlocks < 1)\r
        {\r
                // Hoosterman we've got a problem.\r
                // Can't get space to gc\r
                return -1;\r
        }\r
-       else if(!useReserve && dev->nErasedBlocks <= YAFFS_RESERVED_BLOCKS)\r
-       {\r
-               // We are not in GC, so we hold some in reserve so we can get\r
-               // a gc done.\r
-       }\r
        \r
        // Find an empty block.\r
        \r
@@ -1676,31 +1726,6 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev,int useReserve)
 }\r
 \r
 \r
-static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo)\r
-{\r
-       yaffs_BlockInfo *bi = &dev->blockInfo[blockNo];\r
-       \r
-       // Mark as dirty.\r
-       // If the block is still healthy erase it and mark as clean.\r
-       // If the block has had a data failure, then retire it.\r
-       bi->blockState = YAFFS_BLOCK_STATE_DIRTY;\r
-       \r
-       if(!bi->needsRetiring && yaffs_EraseBlockInNAND(dev,blockNo))\r
-       {\r
-               bi->blockState = YAFFS_BLOCK_STATE_EMPTY;\r
-               dev->nErasedBlocks++;\r
-               bi->pagesInUse = 0;\r
-               bi->pageBits = 0;\r
-       \r
-               T((TSTR("Erased block %d" TENDSTR),blockNo));\r
-       }\r
-       else\r
-       {\r
-               yaffs_RetireBlock(dev,blockNo);\r
-               T((TSTR("**>> Block %d retired" TENDSTR),blockNo));\r
-       }\r
-}\r
-\r
 \r
 static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)\r
 {\r
@@ -1709,10 +1734,16 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
        if(dev->allocationBlock < 0)\r
        {\r
                // Get next block to allocate off\r
-               dev->allocationBlock = yaffs_FindBlockForAllocation(dev,useReserve);\r
+               dev->allocationBlock = yaffs_FindBlockForAllocation(dev);\r
                dev->allocationPage = 0;\r
        }\r
        \r
+       if(!useReserve &&  dev->nErasedBlocks <= YAFFS_RESERVED_BLOCKS)\r
+       {\r
+               // Not enough space to allocate unless we're allowed to use the reserve.\r
+               return -1;\r
+       }\r
+       \r
        // Next page please....\r
        if(dev->allocationBlock >= 0)\r
        {\r
@@ -1733,12 +1764,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
                        dev->allocationBlock = -1;\r
                }\r
 \r
-#ifdef YAFFS_PARANOID\r
-               if(yaffs_CheckChunkErased(dev,retVal) == YAFFS_FAIL)\r
-               {\r
-                       T((TSTR("..................Trying to allocate non-erased page %d" TENDSTR),retVal));\r
-               }\r
-#endif         \r
+\r
                return retVal;\r
                \r
        }\r
@@ -2373,7 +2399,7 @@ int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 *
 // UpdateObjectHeader updates the header on NAND for an object.\r
 // If name is not NULL, then that new name is used.\r
 //\r
-int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name)\r
+int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force)\r
 {\r
 \r
        yaffs_Device *dev = in->myDev;\r
@@ -2388,7 +2414,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name)
     yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bufferNew;\r
     yaffs_ObjectHeader *ohOld = (yaffs_ObjectHeader *)bufferOld;\r
     \r
-    if(!in->fake)\r
+    if(!in->fake || force)\r
     {\r
   \r
                yaffs_CheckGarbageCollection(dev);              \r
@@ -2413,17 +2439,29 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name)
                oh->st_ctime = in->st_ctime;\r
                oh->st_rdev = in->st_rdev;\r
        \r
-               oh->parentObjectId = in->parent->objectId;\r
+               if(in->parent)\r
+               {\r
+                       oh->parentObjectId = in->parent->objectId;\r
+               }\r
+               else\r
+               {\r
+                       oh->parentObjectId = 0;\r
+               }\r
+               \r
                oh->sum = in->sum;\r
                if(name && *name)\r
                {\r
                        memset(oh->name,0,YAFFS_MAX_NAME_LENGTH + 1);\r
                        strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH);\r
                }\r
-               else\r
+               else if(prevChunkId)\r
                {       \r
                        memcpy(oh->name, ohOld->name,YAFFS_MAX_NAME_LENGTH + 1);\r
                }\r
+               else\r
+               {\r
+                       memset(oh->name,0,YAFFS_MAX_NAME_LENGTH + 1);   \r
+               }\r
        \r
                switch(in->variantType)\r
                {\r
@@ -2746,7 +2784,7 @@ int yaffs_FlushFile(yaffs_Object *in)
        \r
                in->st_mtime = CURRENT_TIME;\r
 \r
-               retVal = yaffs_UpdateObjectHeader(in,NULL);\r
+               retVal = yaffs_UpdateObjectHeader(in,NULL,0);\r
        }\r
        else\r
        {\r
@@ -2896,7 +2934,7 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj)
                yaffs_HashObject(hl);\r
                \r
                // Update the hardlink which has become an object\r
-               yaffs_UpdateObjectHeader(hl,NULL);\r
+               yaffs_UpdateObjectHeader(hl,NULL,0);\r
 \r
                // Finally throw away the deleted object\r
                yaffs_DeleteChunk(obj->myDev,obj->chunkId);\r
@@ -3117,6 +3155,11 @@ static int yaffs_Scan(yaffs_Device *dev)
                                if(in->variant.fileVariant.scannedFileSize <endpos)\r
                                {\r
                                        in->variant.fileVariant.scannedFileSize = endpos;\r
+#ifndef CONFIG_YAFFS_USE_HEADER_FILE_SIZE\r
+                                               in->variant.fileVariant.fileSize =      \r
+                                                       in->variant.fileVariant.scannedFileSize;\r
+#endif\r
+\r
                                }\r
                                //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId));  \r
                        }\r
@@ -3153,7 +3196,25 @@ static int yaffs_Scan(yaffs_Device *dev)
                                        }\r
                                }\r
                                \r
-                               if(!in->valid)\r
+                               if(!in->valid &&\r
+                                  (tags.objectId == YAFFS_OBJECTID_ROOT ||\r
+                                   tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))\r
+                               {\r
+                                       // We only load some info, don't fiddle with directory structure\r
+                                       in->valid = 1;\r
+                                       in->variantType = oh->type;\r
+       \r
+                                       in->st_mode  = oh->st_mode;\r
+                                       in->st_uid   = oh->st_uid;\r
+                                       in->st_gid   = oh->st_gid;\r
+                                       in->st_atime = oh->st_atime;\r
+                                       in->st_mtime = oh->st_mtime;\r
+                                       in->st_ctime = oh->st_ctime;\r
+                                       in->st_rdev = oh->st_rdev;\r
+                                       in->chunkId  = chunk;\r
+\r
+                               }\r
+                               else if(!in->valid)\r
                                {\r
                                        // we need to load this info\r
                                \r
@@ -3202,7 +3263,9 @@ static int yaffs_Scan(yaffs_Device *dev)
                                                case YAFFS_OBJECT_TYPE_UNKNOWN:         // Todo got a problem\r
                                                        break;\r
                                                case YAFFS_OBJECT_TYPE_FILE:\r
+#ifdef CONFIG_YAFFS_USE_HEADER_FILE_SIZE\r
                                                        in->variant.fileVariant.fileSize = oh->fileSize;\r
+#endif\r
                                                        break;\r
                                                case YAFFS_OBJECT_TYPE_HARDLINK:\r
                                                        in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;\r
@@ -3496,7 +3559,7 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr)
        \r
        if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size);\r
        \r
-       yaffs_UpdateObjectHeader(obj,NULL);\r
+       yaffs_UpdateObjectHeader(obj,NULL,1);\r
        \r
        return YAFFS_OK;\r
        \r