*** empty log message ***
[yaffs/.git] / yaffs_guts.c
index 47059771ef3727dd21f413947425f20a1a85ec63..7afb1406a444114a9081c1d66d5b6f4af7145389 100644 (file)
  */
  //yaffs_guts.c
 
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.17 2003-01-17 04:19:08 charles Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.28 2003-08-20 03:53:39 charles Exp $";
 
 #include "yportenv.h"
 
 #include "yaffsinterface.h"
 #include "yaffs_guts.h"
 
-
-
-
 #define YAFFS_PASSIVE_GC_CHUNKS 2
 
+#if 0
+// Use Steven Hill's ECC struff instead
 // External functions for ECC on data
 void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
 int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-
+#define yaffs_ECCCalculate(data,ecc) nand_calculate_ecc(data,ecc)
+#define yaffs_ECCCorrect(data,read_ecc,calc_ecc) nand_correct_ecc(data,read_ecc,calc_ecc)
+#else
+#include "yaffs_ecc.h"
+#endif
 
 // countBits is a quick way of counting the number of bits in a byte.
 // ie. countBits[n] holds the number of 1 bits in a byte with the value n.
@@ -216,10 +219,6 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
        int retVal;
        yaffs_Spare localSpare;
 
-       __u8 calcEcc[3];
-       int eccResult1,eccResult2;
-       struct yaffs_NANDSpare nspare;
-
        dev->nPageReads++;
        
        
@@ -240,10 +239,13 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
                {
                        // Do ECC correction
                        //Todo handle any errors
-                       nand_calculate_ecc(data,calcEcc);
-                       eccResult1 = nand_correct_data (data,spare->ecc1, calcEcc);
-                       nand_calculate_ecc(&data[256],calcEcc);
-                       eccResult2 = nand_correct_data (&data[256],spare->ecc2, calcEcc);
+               int eccResult1,eccResult2;
+               __u8 calcEcc[3];
+                
+                       yaffs_ECCCalculate(data,calcEcc);
+                       eccResult1 = yaffs_ECCCorrect (data,spare->ecc1, calcEcc);
+                       yaffs_ECCCalculate(&data[256],calcEcc);
+                       eccResult2 = yaffs_ECCCorrect(&data[256],spare->ecc2, calcEcc);
 
                        if(eccResult1>0)
                        {
@@ -276,6 +278,8 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
        }
        else
        {
+        // Must allocate enough memory for spare+2*sizeof(int) for ecc results from device.
+       struct yaffs_NANDSpare nspare;
                retVal  = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare);
                memcpy (spare, &nspare, sizeof(yaffs_Spare));
                if(data && doErrorCorrection)
@@ -298,7 +302,7 @@ int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
                                T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
                        }
 
-                       if(nspare.eccres2 || nspare.eccres2)
+                       if(nspare.eccres1 || nspare.eccres2)
                        {
                                // Hoosterman, we had a data problem on this page
                                yaffs_HandleReadDataError(dev,chunkInNAND);
@@ -316,12 +320,10 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND
        static int init = 0;
        static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
        static __u8 data[YAFFS_BYTES_PER_CHUNK];
-       static __u8 spare[16];
-       
-       
-       dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare);
-       
-       
+    // Might as well always allocate the larger size for dev->useNANDECC == true;
+       static __u8 spare[sizeof(struct yaffs_NANDSpare)];      
+
+       dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare);
        
        if(!init)
        {
@@ -583,8 +585,8 @@ void yaffs_SetObjectName(yaffs_Object *obj, const char *name)
 
 void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
 {
-       nand_calculate_ecc (data , spare->ecc1);
-       nand_calculate_ecc (&data[256] , spare->ecc2);
+       yaffs_ECCCalculate(data , spare->ecc1);
+       yaffs_ECCCalculate(&data[256] , spare->ecc2);
 }
 
 void yaffs_CalcTagsECC(yaffs_Tags *tags)
@@ -780,11 +782,16 @@ static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn)
 static void yaffs_DeinitialiseTnodes(yaffs_Device*dev)
 {
        // Free the list of allocated tnodes
-       
+       yaffs_TnodeList *tmp;
+               
        while(dev->allocatedTnodeList)
        {
+               tmp =  dev->allocatedTnodeList->next;
+
                YFREE(dev->allocatedTnodeList->tnodes);
-               dev->allocatedTnodeList =  dev->allocatedTnodeList->next;
+               YFREE(dev->allocatedTnodeList);
+               dev->allocatedTnodeList = tmp;
+               
        }
        
        dev->freeTnodes = NULL;
@@ -1149,8 +1156,10 @@ static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level
                        {
                            if(tn->level0[i])
                        {
-                                       
                                        theChunk =  (tn->level0[i] << in->myDev->chunkGroupBits);
+                                       T(YAFFS_TRACE_SCAN,(TSTR("soft delete tch %d cgb %d chunk %d" TENDSTR),
+                                               tn->level0[i],in->myDev->chunkGroupBits,theChunk));
+                                               
                                        theBlock =      yaffs_GetBlockInfo(in->myDev,  theChunk/in->myDev->nChunksPerBlock);
                                        if(theBlock)
                                        {
@@ -1448,10 +1457,15 @@ static void yaffs_DeinitialiseObjects(yaffs_Device *dev)
 {
        // Free the list of allocated Objects
        
+       yaffs_ObjectList *tmp;
+       
        while( dev->allocatedObjectList)
        {
+               tmp =  dev->allocatedObjectList->next;
                YFREE(dev->allocatedObjectList->objects);
-               dev->allocatedObjectList =  dev->allocatedObjectList->next;
+               YFREE(dev->allocatedObjectList);
+               
+               dev->allocatedObjectList =  tmp;
        }
        
        dev->freeObjects = NULL;
@@ -1621,7 +1635,12 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectTyp
                theObject->win_ctime[1] = theObject->win_mtime[1] = theObject->win_atime[1];
 
 #else
-               theObject->st_atime = theObject->st_mtime =     theObject->st_ctime = CURRENT_TIME;
+
+#if defined(CONFIG_KERNEL_2_5)
+               theObject->st_atime = theObject->st_mtime =     theObject->st_ctime = CURRENT_TIME.tv_sec;              
+#else
+               theObject->st_atime = theObject->st_mtime =     theObject->st_ctime = CURRENT_TIME;             
+#endif
 #endif
                switch(type)
                {
@@ -1724,8 +1743,12 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,
                in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];
                in->win_ctime[1] = in->win_mtime[1] = in->win_atime[0];
                
+#else
+#if defined(CONFIG_KERNEL_2_5)
+               in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME.tv_sec;
 #else
                in->st_atime = in->st_mtime = in->st_ctime = CURRENT_TIME;
+#endif
                in->st_rdev  = rdev;
                in->st_uid   = uid;
                in->st_gid   = gid;
@@ -1851,7 +1874,7 @@ int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *
        yaffs_Object *obj;
        int force = 0;
        
-#ifdef YAFFS_CASE_INSENSITIVE
+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
        // Special case for WinCE.
        // While look-up is case insensitive, the name isn't.
        // THerefore we might want to change x.txt to X.txt
@@ -2012,6 +2035,7 @@ static int yaffs_FindDirtiestBlock(yaffs_Device *dev,int aggressive)
        }
        else
        {
+               iterations = dev->endBlock - dev->startBlock + 1;
                iterations = iterations / 16;
                if(iterations > 200)
                {
@@ -2139,7 +2163,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
                dev->allocationPage = 0;
        }
        
-       if(!useReserve &&  dev->nErasedBlocks <= YAFFS_RESERVED_BLOCKS)
+       if(!useReserve &&  dev->nErasedBlocks <= dev->nReservedBlocks)
        {
                // Not enough space to allocate unless we're allowed to use the reserve.
                return -1;
@@ -2181,7 +2205,7 @@ static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
 
 static int yaffs_CheckSpaceForChunkCache(yaffs_Device *dev)
 {
-       return (dev->nErasedBlocks >= YAFFS_RESERVED_BLOCKS);
+       return (dev->nErasedBlocks >= dev->nReservedBlocks);
 }
 
 
@@ -2362,7 +2386,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev)
        
        //yaffs_DoUnlinkedFileDeletion(dev);
        
-       if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + YAFFS_GARBAGE_COLLECT_LOW_WATER))
+       if(dev->nErasedBlocks <= (dev->nReservedBlocks + YAFFS_GARBAGE_COLLECT_LOW_WATER))
        {
                aggressive = 1;
        }               
@@ -2402,7 +2426,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev)
        
        //yaffs_DoUnlinkedFileDeletion(dev);
        
-       if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + 1))
+       if(dev->nErasedBlocks <= (dev->nReservedBlocks + 1))
        {
                aggressive = 1;
        }               
@@ -3126,6 +3150,7 @@ static void yaffs_FlushFilesChunkCache(yaffs_Object *obj)
                                                                                                                        cache->nBytes,1);
 
                                cache->dirty = 0;
+                               cache->object = NULL;
                        }
                
                } while(cache && chunkWritten > 0);
@@ -3158,10 +3183,14 @@ static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev)
                        if(!dev->srCache[i].object)
                        {
                                //T(("Grabbing empty %d\n",i));
+                               
+                               //printf("Grabbing empty %d\n",i);
                        
                                return &dev->srCache[i];
                        }
                }
+               
+               return NULL;
        
                theOne = -1; 
                usage = 0; // just to stop the compiler grizzling
@@ -3178,6 +3207,9 @@ static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev)
                }
        
                //T(("Grabbing non-empty %d\n",theOne));
+               
+               //if(theOne >= 0) printf("Grabbed non-empty cache %d\n",theOne);
+               
                return  theOne >= 0 ?  &dev->srCache[theOne] : NULL;
        }
        else
@@ -3194,6 +3226,7 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
        yaffs_Object *theObj;
        int usage;
        int i;
+       int pushout;
        
        if(dev->nShortOpCaches > 0)
        {
@@ -3210,6 +3243,8 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
                
                        theObj = dev->srCache[0].object;
                        usage = dev->srCache[0].lastUse;
+                       cache = &dev->srCache[0];
+                       pushout = 0;
        
                        for(i = 1; i < dev->nShortOpCaches; i++)
                        {
@@ -3218,15 +3253,27 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
                                {
                                        usage  = dev->srCache[i].lastUse;
                                        theObj = dev->srCache[i].object;
+                                       cache = &dev->srCache[i];
+                                       pushout = i;
                                }
                        }
                
-                       yaffs_FlushFilesChunkCache(theObj);
+                       if(!cache || cache->dirty)
+                       {
+                       
+                               //printf("Dirty ");
+                               yaffs_FlushFilesChunkCache(theObj);
                
-                       // Try again
-                       cache = yaffs_GrabChunkCacheWorker(dev);
+                               // Try again
+                               cache = yaffs_GrabChunkCacheWorker(dev);
+                       }
+                       else
+                       {
+                               //printf(" pushout %d\n",pushout);
+                       }
+                       
                }
-       
+
                return cache;
        }
        else
@@ -3344,6 +3391,7 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB
        int nToCopy;
        int n = nBytes;
        int nDone = 0;
+       yaffs_ChunkCache *cache;
        
        yaffs_Device *dev;
        
@@ -3365,14 +3413,18 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB
                        nToCopy = YAFFS_BYTES_PER_CHUNK - start;
                }
        
-               if(nToCopy != YAFFS_BYTES_PER_CHUNK)
+               cache = yaffs_FindChunkCache(in,chunk);
+               
+               // If the chunk is already in the cache or it is less than a whole chunk
+               // then use the cache (if there is caching)
+               // else bypass the cache.
+               if( cache || nToCopy != YAFFS_BYTES_PER_CHUNK)
                {
-                       // An incomplete start or end chunk (or maybe both start and end chunk)
                        if(dev->nShortOpCaches > 0)
                        {
-                               yaffs_ChunkCache *cache;
+                               
                                // If we can't find the data in the cache, then load it up.
-                               cache = yaffs_FindChunkCache(in,chunk);
+                               
                                if(!cache)
                                {
                                        cache = yaffs_GrabChunkCache(in->myDev);
@@ -3590,7 +3642,7 @@ int yaffs_ResizeFile(yaffs_Object *in, int newSize)
                        // using yaffs_DeleteChunk
 
                        chunkId = yaffs_FindAndDeleteChunkInFile(in,i,NULL);
-                       if(chunkId <= 0 || chunkId >= (dev->endBlock * 32))
+                       if(chunkId < (dev->startBlock * 32) || chunkId >= ((dev->endBlock+1) * 32))
                        {
                                //T(("Found daft chunkId %d for %d\n",chunkId,i));
                        }
@@ -3659,8 +3711,12 @@ int yaffs_FlushFile(yaffs_Object *in, int updateTime)
                {
 #ifdef CONFIG_YAFFS_WINCE
                        yfsd_WinFileTimeNow(in->win_mtime);
+#else
+#if defined(CONFIG_KERNEL_2_5)
+                       in->st_mtime = CURRENT_TIME.tv_sec;
 #else
                        in->st_mtime = CURRENT_TIME;
+#endif
 #endif
                }
 
@@ -4513,9 +4569,15 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr)
        if(valid & ATTR_UID) obj->st_uid = attr->ia_uid;
        if(valid & ATTR_GID) obj->st_gid = attr->ia_gid;
        
+#if defined(CONFIG_KERNEL_2_5)
+       if(valid & ATTR_ATIME) obj->st_atime = attr->ia_atime.tv_sec;
+       if(valid & ATTR_CTIME) obj->st_ctime = attr->ia_ctime.tv_sec;
+       if(valid & ATTR_MTIME) obj->st_mtime = attr->ia_mtime.tv_sec;
+#else
        if(valid & ATTR_ATIME) obj->st_atime = attr->ia_atime;
        if(valid & ATTR_CTIME) obj->st_ctime = attr->ia_ctime;
        if(valid & ATTR_MTIME) obj->st_mtime = attr->ia_mtime;
+#endif
        
        if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size);
        
@@ -4532,10 +4594,15 @@ int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr)
        attr->ia_uid = obj->st_uid;             valid |= ATTR_UID;
        attr->ia_gid = obj->st_gid;             valid |= ATTR_GID;
        
+#if defined(CONFIG_KERNEL_2_5)
+       attr->ia_atime.tv_sec = obj->st_atime;  valid |= ATTR_ATIME;
+       attr->ia_ctime.tv_sec = obj->st_ctime;  valid |= ATTR_CTIME;
+       attr->ia_mtime.tv_sec = obj->st_mtime;  valid |= ATTR_MTIME;
+#else  
        attr->ia_atime = obj->st_atime; valid |= ATTR_ATIME;
        attr->ia_ctime = obj->st_ctime; valid |= ATTR_CTIME;
        attr->ia_mtime = obj->st_mtime; valid |= ATTR_MTIME;
-       
+#endif 
        attr->ia_size = yaffs_GetFileSize(obj); valid |= ATTR_SIZE;
        
        attr->ia_valid = valid;
@@ -4599,6 +4666,20 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        int extraBits;
        int nBlocks;
 
+       if(     dev->nBytesPerChunk != YAFFS_BYTES_PER_CHUNK ||
+       
+               dev->nChunksPerBlock < 2 ||
+               dev->nReservedBlocks < 2 ||
+               dev->startBlock <= 0 ||
+               dev->endBlock <= 0 ||
+               dev->endBlock <= (dev->startBlock + dev->nReservedBlocks)
+         )
+       {
+               //these parameters must be set before stating yaffs
+               // Other parameters startBlock,
+               return YAFFS_FAIL;
+       }
+
 
        
        if(!yaffs_CheckStructures())
@@ -4655,9 +4736,6 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        }
        dev->chunkGroupSize = 1 << dev->chunkGroupBits;
        
-       // Stuff to be taken out later
-       dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
-       dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
        
        
        // More device initialisation
@@ -4742,6 +4820,7 @@ void yaffs_Deinitialise(yaffs_Device *dev)
                yaffs_DeinitialiseBlocks(dev);
                yaffs_DeinitialiseTnodes(dev);
                yaffs_DeinitialiseObjects(dev);
+               YFREE(dev->localBuffer);
        }
        
 }
@@ -4768,7 +4847,7 @@ int  yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
        }
        
        
-       printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree);   
+       // printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree);        
 
        if(nFree < 0) nFree = 0;
 
@@ -4783,6 +4862,7 @@ int  yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
        int nFree;
        int pending;
        int b;
+       int nDirtyCacheChunks=0;
        
        yaffs_BlockInfo *blk;
        
@@ -4830,6 +4910,20 @@ int  yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
 
        nFree += pending;
        
+       // Now count the number of dirty chunks in the cache and subtract those
+       
+       {
+               int i;
+               for(i = 0; i < dev->nShortOpCaches; i++)
+               {
+                       if(dev->srCache[i].dirty) nDirtyCacheChunks++;
+               }
+       }
+       
+       nFree -= nDirtyCacheChunks;
+       
+       nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
+       
        if(nFree < 0) nFree = 0;
 
        return nFree;