-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 &&
- (dev->param.gcControl(dev) & 1) == 0)
- return YAFFS_OK;
-
- if (dev->gcDisable) {
- /* Bail out so we don't get recursive gc */
- return YAFFS_OK;
- }
-
- /* This loop should pass the first time.
- * We'll only see looping here if the collection does not increase space.
- */
-
- do {
- maxTries++;
-
- checkpointBlockAdjust = yaffs2_CalcCheckpointBlocksRequired(dev);
-
- minErased = dev->param.nReservedBlocks + checkpointBlockAdjust + 1;
- erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
-
- /* If we need a block soon then do aggressive gc.*/
- 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 ||
- dev->gcSkip < 1 ||
- background)
- aggressive = 0;
- else {
- dev->gcSkip--;
- break;
- }
- }
-
- dev->gcSkip = 5;
-
- /* If we don't already have a block being gc'd then see if we should start another */
-
- 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) {
- dev->allGCs++;
- if (!aggressive)
- dev->passiveGCs++;
-
- T(YAFFS_TRACE_GC,
- (TSTR
- ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
- dev->nErasedBlocks, aggressive));
-
- gcOk = yaffs_GarbageCollectBlock(dev, dev->gcBlock, aggressive);
- }
-
- if (dev->nErasedBlocks < (dev->param.nReservedBlocks) && dev->gcBlock > 0) {
- T(YAFFS_TRACE_GC,
- (TSTR
- ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
- TENDSTR), dev->nErasedBlocks, maxTries, dev->gcBlock));
- }
- } while ((dev->nErasedBlocks < dev->param.nReservedBlocks) &&
- (dev->gcBlock > 0) &&
- (maxTries < 2));
-
- return aggressive ? gcOk : YAFFS_OK;
-}
-
-/*
- * yaffs_BackgroundGarbageCollect()
- * Garbage collects. Intended to be called from a background thread.
- * Returns non-zero if at least half the free chunks are erased.
- */
-int yaffs_BackgroundGarbageCollect(yaffs_Device *dev, unsigned urgency)
-{
- int erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
-
- T(YAFFS_TRACE_BACKGROUND, (TSTR("Background gc %u" TENDSTR),urgency));
-
- yaffs_CheckGarbageCollection(dev, 1);
- return erasedChunks > dev->nFreeChunks/2;
-}
-
-/*------------------------- TAGS --------------------------------*/
-
-static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId,
- int chunkInObject)
-{
- return (tags->chunkId == chunkInObject &&
- tags->objectId == objectId && !tags->chunkDeleted) ? 1 : 0;
-
-}
-
-
-/*-------------------- Data file manipulation -----------------*/
-
-static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode,
- yaffs_ExtendedTags *tags)
-{
- /*Get the Tnode, then get the level 0 offset chunk offset */
- yaffs_Tnode *tn;
- int theChunk = -1;
- yaffs_ExtendedTags localTags;
- int retVal = -1;
-
- yaffs_Device *dev = in->myDev;
-
- if (!tags) {
- /* Passed a NULL, so use our own tags space */
- tags = &localTags;
- }
-
- tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
-
- if (tn) {
- theChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode);
-
- retVal =
- yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
- chunkInInode);
- }
- return retVal;
-}
-
-static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in, int chunkInInode,
- yaffs_ExtendedTags *tags)
-{
- /* Get the Tnode, then get the level 0 offset chunk offset */
- yaffs_Tnode *tn;
- int theChunk = -1;
- yaffs_ExtendedTags localTags;
-
- yaffs_Device *dev = in->myDev;
- int retVal = -1;
-
- if (!tags) {
- /* Passed a NULL, so use our own tags space */
- tags = &localTags;
- }
-
- tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
-
- if (tn) {
-
- theChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode);
-
- retVal =
- yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
- chunkInInode);
-
- /* Delete the entry in the filestructure (if found) */
- if (retVal != -1)
- yaffs_LoadLevel0Tnode(dev, tn, chunkInInode, 0);
- }
-
- return retVal;
-}
-
-
-int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode,
- int chunkInNAND, int inScan)