- if(!selected && dev->param.isYaffs2 &&
- dev->gcNotDone >= ( background ? 10 : 20)){
- yaffs2_FindOldestDirtySequence(dev);
- if(dev->oldestDirtyBlock > 0) {
- selected = dev->oldestDirtyBlock;
- dev->gcDirtiest = selected;
- dev->oldestDirtyGCs++;
- bi = yaffs_GetBlockInfo(dev, selected);
- dev->gcPagesInUse = bi->pagesInUse - bi->softDeletions;
- } else
- dev->gcNotDone = 0;
- }
-
- if(selected){
- T(YAFFS_TRACE_GC,
- (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR),
- selected,
- dev->param.nChunksPerBlock - dev->gcPagesInUse,
- prioritised));
-
- if(background)
- dev->backgroundGCs++;
- dev->gcDirtiest = 0;
- dev->gcPagesInUse = 0;
- dev->gcNotDone = 0;
- if(dev->refreshSkip > 0)
- dev->refreshSkip--;
- } else{
- dev->gcNotDone++;
- T(YAFFS_TRACE_GC,
- (TSTR("GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s" TENDSTR),
- dev->gcBlockFinder, dev->gcNotDone,
- threshold,
- dev->gcDirtiest, dev->gcPagesInUse,
- dev->oldestDirtyBlock,
- background ? " bg" : ""));
- }
-
- return selected;
-}
-
-/* New garbage collector
- * If we're very low on erased blocks then we do aggressive garbage collection
- * otherwise we do "leasurely" garbage collection.
- * Aggressive gc looks further (whole array) and will accept less dirty blocks.
- * Passive gc only inspects smaller areas and will only accept more dirty blocks.
- *
- * The idea is to help clear out space in a more spread-out manner.
- * Dunno if it really does anything useful.
- */
-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(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;
- }
- if (dev->gcBlock < 1) {
- dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive, background);
- dev->gcChunk = 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));