X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=7e97a5f0eadc0aad888f3ed30c92cf7b1563c3d9;hp=cfb0b4274fa28a408059a80d72cbeaa2ec9ddf02;hb=54d164b5b1fda9b2b25a09efe5cdfe15546e4a36;hpb=2597593cb367f99f68bc3251c27e8b694c7c2a51 diff --git a/yaffs_guts.c b/yaffs_guts.c index cfb0b42..7e97a5f 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -66,15 +66,12 @@ static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, yaffs_ObjectType type); -static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod); +static int yaffs_ApplyXMod(yaffs_Object *obj, char *buffer, yaffs_XAttrMod *xmod); static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj); static int yaffs_CheckStructures(void); static int yaffs_DoGenericObjectDeletion(yaffs_Object *in); -static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev, int blockNo); - - static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, int chunkInNAND); @@ -434,9 +431,9 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, /* let's give it a try */ attempts++; -#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED - bi->skipErasedCheck = 0; -#endif + if(dev->param.alwaysCheckErased) + bi->skipErasedCheck = 0; + if (!bi->skipErasedCheck) { erasedOk = yaffs_CheckChunkErased(dev, chunk); if (erasedOk != YAFFS_OK) { @@ -2106,7 +2103,6 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, int newChunk; int markNAND; int retVal = YAFFS_OK; - int cleanups = 0; int i; int isCheckpointBlock; int matchingChunk; @@ -2224,14 +2220,15 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, * We have to decrement free chunks so this works out properly. */ dev->nFreeChunks--; + bi->softDeletions--; object->nDataChunks--; if (object->nDataChunks <= 0) { /* remeber to clean up the object */ - dev->gcCleanupList[cleanups] = + dev->gcCleanupList[dev->nCleanups] = tags.objectId; - cleanups++; + dev->nCleanups++; } markNAND = 0; } else if (0) { @@ -2317,8 +2314,23 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); + + } + + yaffs_VerifyCollectedBlock(dev, bi, block); + + + + if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) { + /* + * The gc did not complete. Set block state back to FULL + * because checkpointing does not restore gc. + */ + bi->blockState = YAFFS_BLOCK_STATE_FULL; + } else { + /* The gc completed. */ /* Do any required cleanups */ - for (i = 0; i < cleanups; i++) { + for (i = 0; i < dev->nCleanups; i++) { /* Time to delete the file too */ object = yaffs_FindObjectByNumber(dev, @@ -2338,20 +2350,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, } - } - - yaffs_VerifyCollectedBlock(dev, bi, block); - - - if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) { - /* - * The gc did not complete. Set block state back to FULL - * because checkpointing does not restore gc. - */ - bi->blockState = YAFFS_BLOCK_STATE_FULL; - } else { - /* The gc completed. */ chunksAfter = yaffs_GetErasedChunks(dev); if (chunksBefore >= chunksAfter) { T(YAFFS_TRACE_GC, @@ -2361,6 +2360,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, } dev->gcBlock = 0; dev->gcChunk = 0; + dev->nCleanups = 0; } dev->gcDisable = 0; @@ -2432,7 +2432,16 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, threshold = dev->param.nChunksPerBlock; iterations = nBlocks; } else { - int maxThreshold = dev->param.nChunksPerBlock/2; + int maxThreshold; + + if(background) + maxThreshold = dev->param.nChunksPerBlock/2; + else + maxThreshold = dev->param.nChunksPerBlock/8; + + if(maxThreshold < YAFFS_GC_PASSIVE_THRESHOLD) + maxThreshold = YAFFS_GC_PASSIVE_THRESHOLD; + threshold = background ? (dev->gcNotDone + 2) * 2 : 0; if(threshold param.nChunksPerBlock - dev->gcPagesInUse, prioritised)); + dev->nGCBlocks++; if(background) dev->backgroundGCs++; + dev->gcDirtiest = 0; dev->gcPagesInUse = 0; dev->gcNotDone = 0; @@ -2532,10 +2543,8 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background) int aggressive = 0; int gcOk = YAFFS_OK; int maxTries = 0; - int minErased; int erasedChunks; - int checkpointBlockAdjust; if(dev->param.gcControl && @@ -2563,6 +2572,9 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background) if (dev->nErasedBlocks < minErased) aggressive = 1; else { + if(!background && erasedChunks > (dev->nFreeChunks / 4)) + break; + if(dev->gcSkip > 20) dev->gcSkip = 20; if(erasedChunks < dev->nFreeChunks/2 || @@ -2582,10 +2594,12 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background) if (dev->gcBlock < 1 && !aggressive) { dev->gcBlock = yaffs2_FindRefreshBlock(dev); dev->gcChunk = 0; + dev->nCleanups=0; } if (dev->gcBlock < 1) { dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive, background); dev->gcChunk = 0; + dev->nCleanups=0; } if (dev->gcBlock > 0) { @@ -2994,7 +3008,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, int newChunkId; yaffs_ExtendedTags newTags; yaffs_ExtendedTags oldTags; - YCHAR *alias = NULL; + const YCHAR *alias = NULL; __u8 *buffer = NULL; YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1]; @@ -3095,7 +3109,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, /* process any xattrib modifications */ if(xmod) - yaffs_ApplyXMod(dev, (char *)buffer, xmod); + yaffs_ApplyXMod(in, (char *)buffer, xmod); /* Tags */ @@ -4185,6 +4199,9 @@ static void yaffs_StripDeletedObjects(yaffs_Device *dev) struct ylist_head *n; yaffs_Object *l; + if (dev->readOnly) + return; + /* Soft delete all the unlinked files */ ylist_for_each_safe(i, n, &dev->unlinkedDir->variant.directoryVariant.children) { @@ -4238,6 +4255,8 @@ static void yaffs_FixHangingObjects(yaffs_Device *dev) int depthLimit; int hanging; + if (dev->readOnly) + return; /* Iterate through the objects in each hash entry, * looking at each object. @@ -4917,10 +4936,11 @@ static int yaffs_DoXMod(yaffs_Object *obj, int set, const YCHAR *name, const voi return -ENOSPC; } -static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod) +static int yaffs_ApplyXMod(yaffs_Object *obj, char *buffer, yaffs_XAttrMod *xmod) { int retval = 0; int x_offs = sizeof(yaffs_ObjectHeader); + yaffs_Device *dev = obj->myDev; int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader); char * x_buffer = buffer + x_offs; @@ -4930,6 +4950,9 @@ static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod else retval = nval_del(x_buffer, x_size, xmod->name); + obj->hasXattr = nval_hasvalues(x_buffer, x_size); + obj->xattrKnown = 1; + xmod->result = retval; return retval; @@ -4944,30 +4967,45 @@ static int yaffs_DoXFetch(yaffs_Object *obj, const YCHAR *name, void *value, int int x_offs = sizeof(yaffs_ObjectHeader); int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader); - __u8 * x_buffer; + char * x_buffer; int retval = 0; if(obj->hdrChunk < 1) return -ENODATA; - buffer = yaffs_GetTempBuffer(dev, __LINE__); + /* If we know that the object has no xattribs then don't do all the + * reading and parsing. + */ + if(obj->xattrKnown && !obj->hasXattr){ + if(name) + return -ENODATA; + else + return 0; + } + + buffer = (char *) yaffs_GetTempBuffer(dev, __LINE__); if(!buffer) return -ENOMEM; - result = yaffs_ReadChunkWithTagsFromNAND(dev,obj->hdrChunk, buffer, &tags); + result = yaffs_ReadChunkWithTagsFromNAND(dev,obj->hdrChunk, (__u8 *)buffer, &tags); if(result != YAFFS_OK) retval = -ENOENT; else{ x_buffer = buffer + x_offs; + if (!obj->xattrKnown){ + obj->hasXattr = nval_hasvalues(x_buffer, x_size); + obj->xattrKnown = 1; + } + if(name) retval = nval_get(x_buffer, x_size, name, value, size); else retval = nval_list(x_buffer, x_size, value,size); } - yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); + yaffs_ReleaseTempBuffer(dev,(__u8 *)buffer,__LINE__); return retval; } @@ -5497,9 +5535,8 @@ static int yaffs_CheckStructures(void) /* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */ /* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */ /* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */ -#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG /* yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); */ -#endif + #ifndef CONFIG_YAFFS_WINCE yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader"); #endif