changeset 246:8a37f364d258

gc part of the block at a time to reduce latency
author charles
date Thu, 27 Nov 2008 02:46:45 +0000
parents 87755cd7272a
children a759c32d15f1
files yaffs_guts.c yaffs_guts.h
diffstat 2 files changed, 41 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -2993,17 +2993,17 @@ static int yaffs_GetErasedChunks(yaffs_D
 
 }
 
-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;
@@ -3019,8 +3019,11 @@ static int yaffs_GarbageCollectBlock(yaf
 	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); */
 
@@ -3046,14 +3049,20 @@ static int yaffs_GarbageCollectBlock(yaf
 		
 		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;
 
@@ -3068,8 +3077,8 @@ static int yaffs_GarbageCollectBlock(yaf
 
 				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)){
@@ -3184,6 +3193,7 @@ static int yaffs_GarbageCollectBlock(yaf
 		}
 
 		yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
+		
 
 
 		/* Do any required cleanups */
@@ -3218,6 +3228,12 @@ static int yaffs_GarbageCollectBlock(yaf
 		    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;
@@ -3265,7 +3281,12 @@ static int yaffs_CheckGarbageCollection(
 			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++;
@@ -3278,7 +3299,7 @@ static int yaffs_CheckGarbageCollection(
 			   ("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) {
@@ -3287,8 +3308,9 @@ static int yaffs_CheckGarbageCollection(
 			   ("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;
 }
@@ -7221,6 +7243,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
 	dev->blockOffset = 0;
 	dev->chunkOffset = 0;
 	dev->nFreeChunks = 0;
+	
+	dev->gcBlock = -1;
 
 	if (dev->startBlock == 0) {
 		dev->internalStartBlock = dev->startBlock + 1;
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -691,6 +691,8 @@ struct yaffs_DeviceStruct {
 	yaffs_TnodeList *allocatedTnodeList;
 
 	int isDoingGC;
+	int gcBlock;
+	int gcChunk;
 
 	int nObjectsCreated;
 	yaffs_Object *freeObjects;