*** empty log message ***
[yaffs/.git] / yaffs_guts.c
index bfe10b74deb2aa6140d47fe876831f1a2b695ad2..975d7c0ad3dd28f55712290fb5ef19f380cb763c 100644 (file)
@@ -14,7 +14,7 @@
  */
  //yaffs_guts.c
 
-const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.10 2002-09-27 20:50:50 charles Exp $";
+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.11 2002-10-02 02:11:25 charles Exp $";
 
 #include "yportenv.h"
 
@@ -109,12 +109,8 @@ static int yaffs_CheckFileSanity(yaffs_Object *in);
 #define yaffs_CheckFileSanity(in)
 #endif
 
-#ifdef CONFIG_YAFFS_SHORT_OP_CACHE
-static void yaffs_InvalidateChunkCache(yaffs_Object *in);
-#define        yaffs_INVALIDATECHUNKCACHE(in) yaffs_InvalidateChunkCache(in)
-#else
-#define yaffs_INVALIDATECHUNKCACHE(in)
-#endif
+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in);
+static void yaffs_InvalidateChunkCache(yaffs_Device *dev, int objectId, int chunkId);
 
 
 static  __inline__ yaffs_BlockInfo* yaffs_GetBlockInfo(yaffs_Device *dev, int blk)
@@ -1542,7 +1538,7 @@ yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *e
 }
 
 
-static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const char *newName)
+static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const char *newName,int force)
 {
        int unlinkOp;
 
@@ -1556,9 +1552,10 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const
        // If the object is a file going into the unlinked directory, then it is OK to just stuff it in since
        // duplicate names are allowed.
        // Otherwise only proceed if the new name does not exist and if we're putting it into a directory.
-       if( unlinkOp||
-           (!yaffs_FindObjectByName(newDir,newName) &&
-            newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY))
+       if( (unlinkOp|| 
+                force || 
+                !yaffs_FindObjectByName(newDir,newName))  &&
+            newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
        {
                obj->sum = yaffs_CalcNameSum(newName);
                obj->dirty = 1;
@@ -1580,11 +1577,22 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const
 int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName)
 {
        yaffs_Object *obj;
+       int force = 0;
+       
+#if WIN32
+       // 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
+       if(oldDir == newDir && stricmp(oldName,newName) == 0)
+       {
+               force = 1;
+       }       
+#endif
        
        obj = yaffs_FindObjectByName(oldDir,oldName);
        if(obj && obj->renameAllowed)
        {
-               return yaffs_ChangeObjectName(obj,newDir,newName);
+               return yaffs_ChangeObjectName(obj,newDir,newName,force);
        }
        return YAFFS_FAIL;
 }
@@ -1962,9 +1970,19 @@ static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev)
        if(dev->unlinkedDeletion)
        {
                yaffs_Object *obj = dev->unlinkedDeletion;
-               int limit;
                int delresult;
-               limit = 50; // Max number of chunks to delete in a file. NB this can be exceeded, but not by much.
+               int limit; // Number of chunks to delete in a file.
+                                  // NB this can be exceeded, but not by much.
+                                  
+               if(dev->nErasedBlocks <= (YAFFS_RESERVED_BLOCKS + YAFFS_GARBAGE_COLLECT_LOW_WATER))
+               {
+                       limit = 50; // Doing GC soon, so dig deeper     
+               }
+               else
+               {
+                       limit = 5;
+               }
+               
                delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit);
                
                if(obj->nDataChunks == 0)
@@ -2563,7 +2581,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force)
     yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bufferNew;
     yaffs_ObjectHeader *ohOld = (yaffs_ObjectHeader *)bufferOld;
 
-       yaffs_INVALIDATECHUNKCACHE(in);
+    yaffs_InvalidateWholeChunkCache(in);
     
     if(!in->fake || force)
     {
@@ -2705,23 +2723,6 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const char *name, int force)
 
 #ifdef CONFIG_YAFFS_SHORT_OP_CACHE
 
-// Invalidate all the cache pages associated with this object
-// Do this whenever ther file is modified... dumb as a rock remember!
-static void yaffs_InvalidateChunkCache(yaffs_Object *in)
-{
-       int i;
-       yaffs_Device *dev = in->myDev;
-       int id = in->objectId;
-       
-       for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
-       {
-               if(dev->srCache[i].objectId == id)
-               {
-                       dev->srCache[i].objectId = 0;
-               }
-       }
-}
-
 
 // Grab us a chunk for use.
 // First look for an empty one. 
@@ -2802,6 +2803,61 @@ static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache)
 
 }
 
+// Invalidate a single cache page
+static void yaffs_InvalidateChunkCache(yaffs_Device *dev, int objectId, int chunkId)
+{
+       yaffs_ChunkCache *cache = yaffs_FindChunkCache(dev,objectId,chunkId);
+
+       if(cache)
+       {
+               cache->objectId = 0;
+       }
+}
+
+
+// Invalidate all the cache pages associated with this object
+// Do this whenever ther file is modified... dumb as a rock remember!
+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)
+{
+       int i;
+       yaffs_Device *dev = in->myDev;
+       int id = in->objectId;
+       
+       for(i = 0; i < YAFFS_N_CACHE_CHUNKS; i++)
+       {
+               if(dev->srCache[i].objectId == id)
+               {
+                       dev->srCache[i].objectId = 0;
+               }
+       }
+}
+
+
+#else
+
+static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
+{
+       return NULL;    
+}
+
+
+static yaffs_ChunkCache *yaffs_FindChunkCache(yaffs_Device *dev, int objectId, int chunkId)
+{
+       return NULL;
+}
+
+static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache)
+{
+}
+
+static void yaffs_InvalidateChunkCache(yaffs_Device *dev, int objectId, int chunkId)
+{
+}
+
+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)
+{
+}
+
 
 
 #endif
@@ -2828,6 +2884,7 @@ int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nB
 
        __u8 localBuffer[YAFFS_BYTES_PER_CHUNK];
        
+       
        int chunk;
        int start;
        int nToCopy;
@@ -2909,8 +2966,10 @@ int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, in
        int nToWriteBack;
        int endOfWrite = offset+nBytes;
        int chunkWritten = 0;
+       int nBytesRead;
+       
+       yaffs_InvalidateWholeChunkCache(in);
        
-       yaffs_INVALIDATECHUNKCACHE(in);
        
        while(n > 0 && chunkWritten >= 0)
        {
@@ -2920,10 +2979,23 @@ int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, in
 
                // OK now check for the curveball where the start and end are in
                // the same chunk.
+               
                if(     (start + n) < YAFFS_BYTES_PER_CHUNK)
                {
                        nToCopy = n;
-                       nToWriteBack = (start + n);
+                       
+                       // Now folks, to calculate how many bytes to write back....
+                       // If we're overwriting and not writing to then end of file then
+                       // we need to write back as much as was there before.
+                       
+                       nBytesRead = in->variant.fileVariant.fileSize - ((chunk -1) * YAFFS_BYTES_PER_CHUNK);
+                       
+                       if(nBytesRead > YAFFS_BYTES_PER_CHUNK)
+                       {
+                               nBytesRead = YAFFS_BYTES_PER_CHUNK;
+                       }
+                       nToWriteBack = (nBytesRead > (start + n)) ? nBytesRead : (start +n);
+                       
                }
                else
                {
@@ -2942,7 +3014,7 @@ int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, in
                        
                        chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,localBuffer,nToWriteBack,0);
                        
-                       //T(("Write with readback to chunk %d %d\n",chunk,chunkWritten));
+                       //T(("Write with readback to chunk %d %d  start %d  copied %d wrote back %d\n",chunk,chunkWritten,start, nToCopy, nToWriteBack));
                        
                }
                else
@@ -2957,6 +3029,8 @@ int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, in
                        // A full chunk. Write directly from the supplied buffer.
                        chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,buffer,YAFFS_BYTES_PER_CHUNK,0);
 #endif
+                       // Since we've overwritten the cached data, we better invalidate it.
+                       yaffs_InvalidateChunkCache(in->myDev,in->objectId,chunk);
                        //T(("Write to chunk %d %d\n",chunk,chunkWritten));
                }
                
@@ -2995,7 +3069,7 @@ int yaffs_ResizeFile(yaffs_Object *in, int newSize)
        
        __u8 localBuffer[YAFFS_BYTES_PER_CHUNK];
 
-       yaffs_INVALIDATECHUNKCACHE(in);
+       yaffs_InvalidateWholeChunkCache(in);
        
        if(in->variantType != YAFFS_OBJECT_TYPE_FILE)
        {
@@ -3099,7 +3173,7 @@ int yaffs_FlushFile(yaffs_Object *in)
 
 static int yaffs_DoGenericObjectDeletion(yaffs_Object *in)
 {
-       yaffs_INVALIDATECHUNKCACHE(in);
+       yaffs_InvalidateWholeChunkCache(in);
        yaffs_RemoveObjectFromDirectory(in);
        yaffs_DeleteChunk(in->myDev,in->chunkId);
 #if __KERNEL__
@@ -3135,7 +3209,7 @@ static int yaffs_UnlinkFile(yaffs_Object *in)
 #else
        int retVal;
        int immediateDeletion=0;
-       retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL);
+       retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL,0);
        if(retVal == YAFFS_OK)
        {
                //in->unlinked = 1;
@@ -3331,7 +3405,7 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj)
                
                yaffs_GetObjectName(hl,name,YAFFS_MAX_NAME_LENGTH+1);
                
-               retVal = yaffs_ChangeObjectName(obj, hl->parent, name);
+               retVal = yaffs_ChangeObjectName(obj, hl->parent, name,0);
                
                if(retVal == YAFFS_OK)
                {