*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.66 2008-11-26 20:46:47 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.67 2008-11-27 02:46:45 charles Exp $";
#include "yportenv.h"
}
-static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
+static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlock)
{
int oldChunk;
int newChunk;
- int chunkInBlock;
int markNAND;
int retVal = YAFFS_OK;
int cleanups = 0;
int i;
int isCheckpointBlock;
int matchingChunk;
+ int maxCopies;
int chunksBefore = yaffs_GetErasedChunks(dev);
int chunksAfter;
bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
T(YAFFS_TRACE_TRACING,
- (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
- bi->pagesInUse, bi->hasShrinkHeader));
+ (TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR),
+ block,
+ bi->pagesInUse,
+ bi->hasShrinkHeader,
+ wholeBlock));
/*yaffs_VerifyFreeChunks(dev); */
yaffs_VerifyBlock(dev,bi,block);
- for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
+ maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10;
+ oldChunk = block * dev->nChunksPerBlock + dev->gcChunk;
+
+ for ( /* init already done */;
retVal == YAFFS_OK &&
- chunkInBlock < dev->nChunksPerBlock
- && yaffs_StillSomeChunkBits(dev, block);
- chunkInBlock++, oldChunk++) {
- if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
+ dev->gcChunk < dev->nChunksPerBlock &&
+ (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING)&&
+ maxCopies > 0;
+ dev->gcChunk++, oldChunk++) {
+ if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) {
/* This page is in use and might need to be copied off */
+
+ maxCopies--;
markNAND = 1;
T(YAFFS_TRACE_GC_DETAIL,
(TSTR
- ("Collecting page %d, %d %d %d " TENDSTR),
- chunkInBlock, tags.objectId, tags.chunkId,
+ ("Collecting chunk in block %d, %d %d %d " TENDSTR),
+ dev->gcChunk, tags.objectId, tags.chunkId,
tags.byteCount));
if(object && !yaffs_SkipVerification(dev)){
}
yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
+
/* Do any required cleanups */
TENDSTR), chunksBefore, chunksAfter));
}
+ /* If the gc completed then clear the current gcBlock so that we find another. */
+ if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING){
+ dev->gcBlock = -1;
+ dev->gcChunk = 0;
+ }
+
dev->isDoingGC = 0;
return retVal;
aggressive = 0;
}
- block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
+ if(dev->gcBlock <= 0){
+ dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive);
+ dev->gcChunk = 0;
+ }
+
+ block = dev->gcBlock;
if (block > 0) {
dev->garbageCollections++;
("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
dev->nErasedBlocks, aggressive));
- gcOk = yaffs_GarbageCollectBlock(dev, block);
+ gcOk = yaffs_GarbageCollectBlock(dev,block,aggressive);
}
if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
TENDSTR), dev->nErasedBlocks, maxTries, block));
}
- } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
- && (maxTries < 2));
+ } while ((dev->nErasedBlocks < dev->nReservedBlocks) &&
+ (block > 0) &&
+ (maxTries < 2));
return aggressive ? gcOk : YAFFS_OK;
}
dev->blockOffset = 0;
dev->chunkOffset = 0;
dev->nFreeChunks = 0;
+
+ dev->gcBlock = -1;
if (dev->startBlock == 0) {
dev->internalStartBlock = dev->startBlock + 1;