*/
//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"
#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)
}
-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;
// 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;
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;
}
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)
yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bufferNew;
yaffs_ObjectHeader *ohOld = (yaffs_ObjectHeader *)bufferOld;
- yaffs_INVALIDATECHUNKCACHE(in);
+ yaffs_InvalidateWholeChunkCache(in);
if(!in->fake || 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.
}
+// 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
__u8 localBuffer[YAFFS_BYTES_PER_CHUNK];
+
int chunk;
int start;
int nToCopy;
int nToWriteBack;
int endOfWrite = offset+nBytes;
int chunkWritten = 0;
+ int nBytesRead;
+
+ yaffs_InvalidateWholeChunkCache(in);
- yaffs_INVALIDATECHUNKCACHE(in);
while(n > 0 && chunkWritten >= 0)
{
// 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
{
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
// 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));
}
__u8 localBuffer[YAFFS_BYTES_PER_CHUNK];
- yaffs_INVALIDATECHUNKCACHE(in);
+ yaffs_InvalidateWholeChunkCache(in);
if(in->variantType != YAFFS_OBJECT_TYPE_FILE)
{
static int yaffs_DoGenericObjectDeletion(yaffs_Object *in)
{
- yaffs_INVALIDATECHUNKCACHE(in);
+ yaffs_InvalidateWholeChunkCache(in);
yaffs_RemoveObjectFromDirectory(in);
yaffs_DeleteChunk(in->myDev,in->chunkId);
#if __KERNEL__
#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;
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)
{