X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=7fc606d7c579639425b1365a68fec310569eade0;hp=60227dffee59c50da79f5b13754e2dde20e73c26;hb=8346993dc47142001ad9c566485c318052788c60;hpb=69eb82df82adeab5210e170f85d0e08610b728a6 diff --git a/yaffs_guts.c b/yaffs_guts.c index 60227df..7fc606d 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,7 +12,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.114 2010-03-07 22:07:03 charles Exp $"; + "$Id: yaffs_guts.c,v 1.117 2010-03-11 02:44:43 charles Exp $"; #include "yportenv.h" #include "yaffs_trace.h" @@ -1062,7 +1062,9 @@ static int yaffs_CalcOldestDirtySequence(yaffs_Device *dev) __u32 seq; yaffs_BlockInfo *b = 0; - + if(!dev->param.isYaffs2) + return 0; + /* Find the oldest dirty sequence number. */ seq = dev->sequenceNumber; for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { @@ -1078,7 +1080,7 @@ static int yaffs_CalcOldestDirtySequence(yaffs_Device *dev) static void yaffs_FindOldestDirtySequence(yaffs_Device *dev) { - if(!dev->oldestDirtySequence) + if(dev->param.isYaffs2 && !dev->oldestDirtySequence) dev->oldestDirtySequence = yaffs_CalcOldestDirtySequence(dev); @@ -1099,6 +1101,9 @@ static void yaffs_FindOldestDirtySequence(yaffs_Device *dev) static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi) { + if(!dev->param.isYaffs2) + return; + if(!bi || bi->sequenceNumber == dev->oldestDirtySequence) dev->oldestDirtySequence = 0; } @@ -1110,7 +1115,7 @@ static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *b */ static void yaffs_UpdateOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi) { - if(dev->oldestDirtySequence){ + if(dev->param.isYaffs2 && dev->oldestDirtySequence){ if(dev->oldestDirtySequence > bi->sequenceNumber) dev->oldestDirtySequence = bi->sequenceNumber; } @@ -1798,6 +1803,7 @@ static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk) if (theBlock) { theBlock->softDeletions++; dev->nFreeChunks++; + yaffs_UpdateOldestDirtySequence(dev,theBlock); } } @@ -2352,6 +2358,8 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, case YAFFS_OBJECT_TYPE_DIRECTORY: YINIT_LIST_HEAD(&theObject->variant.directoryVariant. children); + YINIT_LIST_HEAD(&theObject->variant.directoryVariant. + dirty); break; case YAFFS_OBJECT_TYPE_SYMLINK: case YAFFS_OBJECT_TYPE_HARDLINK: @@ -3334,14 +3342,20 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, yaffs_ObjectHeader *oh; oh = (yaffs_ObjectHeader *)buffer; + oh->isShrink = 0; tags.extraIsShrinkHeader = 0; + oh->shadowsObject = 0; oh->inbandShadowsObject = 0; - if(object->variantType == YAFFS_OBJECT_TYPE_FILE) - oh->fileSize = object->variant.fileVariant.fileSize; tags.extraShadows = 0; + /* Update file size */ + if(object->variantType == YAFFS_OBJECT_TYPE_FILE){ + oh->fileSize = object->variant.fileVariant.fileSize; + tags.extraFileLength = oh->fileSize; + } + yaffs_VerifyObjectHeader(object, oh, &tags, 1); newChunk = yaffs_WriteNewChunkWithTagsToNAND(dev,(__u8 *) oh, &tags, 1); @@ -4850,9 +4864,9 @@ static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) dev->blocksInCheckpoint > 0) { dev->isCheckpointed = 0; yaffs_CheckpointInvalidateStream(dev); - if (dev->param.markSuperBlockDirty) - dev->param.markSuperBlockDirty(dev); } + if (dev->param.markSuperBlockDirty) + dev->param.markSuperBlockDirty(dev); } @@ -5463,6 +5477,10 @@ int retVal = -1; retVal = yaffs_DeleteFile(obj); break; case YAFFS_OBJECT_TYPE_DIRECTORY: + if(!ylist_empty(&obj->variant.directoryVariant.dirty)){ + T(YAFFS_TRACE_BACKGROUND, (TSTR("Remove object %d from dirty directories" TENDSTR),obj->objectId)); + ylist_del_init(&obj->variant.directoryVariant.dirty); + } return yaffs_DeleteDirectory(obj); break; case YAFFS_OBJECT_TYPE_SYMLINK: @@ -5537,6 +5555,7 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj) return yaffs_DeleteFile(obj); break; case YAFFS_OBJECT_TYPE_DIRECTORY: + ylist_del_init(&obj->variant.directoryVariant.dirty); return yaffs_DeleteDirectory(obj); break; case YAFFS_OBJECT_TYPE_SYMLINK: @@ -7045,17 +7064,57 @@ static void yaffs_VerifyDirectory(yaffs_Object *directory) * create dir/a : update dir's mtime/ctime * rm dir/a: update dir's mtime/ctime * modify dir/a: don't update dir's mtimme/ctime + * + * This can be handled immediately or defered. Defering helps reduce the number + * of updates when many files in a directory are changed within a brief period. + * + * If the directory updating is defered then yaffs_UpdateDirtyDirecories must be + * called periodically. */ static void yaffs_UpdateParent(yaffs_Object *obj) { + yaffs_Device *dev; if(!obj) return; + dev = obj->myDev; obj->dirty = 1; obj->yst_mtime = obj->yst_ctime = Y_CURRENT_TIME; + if(dev->param.deferDirectoryUpdate){ + struct ylist_head *link = &obj->variant.directoryVariant.dirty; + + if(ylist_empty(link)){ + ylist_add(link,&dev->dirtyDirectories); + T(YAFFS_TRACE_BACKGROUND, (TSTR("Added object %d to dirty directories" TENDSTR),obj->objectId)); + } - yaffs_UpdateObjectHeader(obj,NULL,0,0,0); + } else + yaffs_UpdateObjectHeader(obj,NULL,0,0,0); +} + +void yaffs_UpdateDirtyDirectories(yaffs_Device *dev) +{ + struct ylist_head *link; + yaffs_Object *obj; + yaffs_DirectoryStructure *dS; + yaffs_ObjectVariant *oV; + + T(YAFFS_TRACE_BACKGROUND, (TSTR("Update dirty directories" TENDSTR))); + + while(!ylist_empty(&dev->dirtyDirectories)){ + link = dev->dirtyDirectories.next; + ylist_del_init(link); + + dS=ylist_entry(link,yaffs_DirectoryStructure,dirty); + oV = ylist_entry(dS,yaffs_ObjectVariant,directoryVariant); + obj = ylist_entry(oV,yaffs_Object,variant); + + T(YAFFS_TRACE_BACKGROUND, (TSTR("Update directory %d" TENDSTR), obj->objectId)); + + if(obj->dirty) + yaffs_UpdateObjectHeader(obj,NULL,0,0,0); + } } static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj) @@ -7666,6 +7725,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev) dev->nErasedBlocks = 0; dev->isDoingGC = 0; dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */ + YINIT_LIST_HEAD(&dev->dirtyDirectories); dev->oldestDirtySequence = 0; /* Initialise temporary buffers and caches. */