changeset 370:8f4ecc1911fe

Dynamically update the oldest dirty sequence number so that it does not have to be recalculated all the time
author charles <charles>
date Sun, 07 Mar 2010 22:07:03 +0000
parents 4c13be92e208
children 5cc599caef44
files yaffs_guts.c
diffstat 1 files changed, 77 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -12,7 +12,7 @@
  */
 
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.113 2010-03-05 02:26:27 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.114 2010-03-07 22:07:03 charles Exp $";
 
 #include "yportenv.h"
 #include "yaffs_trace.h"
@@ -1047,6 +1047,75 @@ static int yaffs_WriteNewChunkWithTagsTo
 	return chunk;
 }
 
+
+/*
+ * Oldest Dirty Sequence Number handling.
+ */
+ 
+/* yaffs_CalcOldestDirtySequence()
+ * yaffs_FindOldestDirtySequence()
+ * Calculate the oldest dirty sequence number if we don't know it.
+ */
+static int yaffs_CalcOldestDirtySequence(yaffs_Device *dev)
+{
+	int i;
+	__u32 seq;
+	yaffs_BlockInfo *b = 0;
+
+	
+	/* Find the oldest dirty sequence number. */
+	seq = dev->sequenceNumber;
+	for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
+		b = yaffs_GetBlockInfo(dev, i);
+		if (b->blockState == YAFFS_BLOCK_STATE_FULL &&
+		    (b->pagesInUse - b->softDeletions) < dev->param.nChunksPerBlock &&
+		    b->sequenceNumber < seq) 
+				seq = b->sequenceNumber;
+	}
+	return seq;
+}
+
+
+static void yaffs_FindOldestDirtySequence(yaffs_Device *dev)
+{
+	if(!dev->oldestDirtySequence)
+		dev->oldestDirtySequence = 
+			yaffs_CalcOldestDirtySequence(dev);
+
+#if 0
+	if(!yaffs_SkipVerification(dev) &&
+		dev->oldestDirtySequence != yaffs_CalcOldestDirtySequence(dev))
+		YBUG();
+
+#endif
+}
+
+/*
+ * yaffs_ClearOldestDirtySequence()
+ * Called when a block is erased or marked bad. (ie. when its sequenceNumber
+ * becomes invalid). If the value matches the oldest then we clear 
+ * dev->oldestDirtySequence to force its recomputation.
+ */
+static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi)
+{
+
+	if(!bi || bi->sequenceNumber == dev->oldestDirtySequence)
+		dev->oldestDirtySequence = 0;
+}
+
+/*
+ * yaffs_UpdateOldestDirtySequence()
+ * Update the oldest dirty sequence number whenever we dirty a block.
+ * Only do this if the oldestDirtySequence is actually being tracked.
+ */
+static void yaffs_UpdateOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi)
+{
+	if(dev->oldestDirtySequence){
+		if(dev->oldestDirtySequence > bi->sequenceNumber)
+			dev->oldestDirtySequence = bi->sequenceNumber;
+	}
+}
+ 
 /*
  * Block retiring for handling a broken block.
  */
@@ -1056,6 +1125,8 @@ static void yaffs_RetireBlock(yaffs_Devi
 	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
 
 	yaffs_InvalidateCheckpoint(dev);
+	
+	yaffs_ClearOldestDirtySequence(dev,bi);
 
 	if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) {
 		if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) {
@@ -2665,9 +2736,6 @@ static void yaffs_DeinitialiseBlocks(yaf
 static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
 					yaffs_BlockInfo *bi)
 {
-	int i;
-	__u32 seq;
-	yaffs_BlockInfo *b;
 
 	if (!dev->param.isYaffs2)
 		return 1;	/* disqualification only applies to yaffs2. */
@@ -2675,23 +2743,7 @@ static int yaffs_BlockNotDisqualifiedFro
 	if (!bi->hasShrinkHeader)
 		return 1;	/* can gc */
 
-	/* Find the oldest dirty sequence number if we don't know it and save it
-	 * so we don't have to keep recomputing it.
-	 */
-	if (!dev->oldestDirtySequence) {
-		seq = dev->sequenceNumber;
-
-		for (i = dev->internalStartBlock; i <= dev->internalEndBlock;
-				i++) {
-			b = yaffs_GetBlockInfo(dev, i);
-			if (b->blockState == YAFFS_BLOCK_STATE_FULL &&
-			    (b->pagesInUse - b->softDeletions) <
-			    dev->param.nChunksPerBlock && b->sequenceNumber < seq) {
-				seq = b->sequenceNumber;
-			}
-		}
-		dev->oldestDirtySequence = seq;
-	}
+	yaffs_FindOldestDirtySequence(dev);
 
 	/* Can't do gc of this block if there are any blocks older than this one that have
 	 * discarded pages.
@@ -2859,8 +2911,6 @@ static int yaffs_FindBlockForGarbageColl
 		   dev->param.nChunksPerBlock - pagesInUse, prioritised));
 	}
 
-	dev->oldestDirtySequence = 0;
-
 	if (dirtiest > 0)
 		dev->nonAggressiveSkip = 4;
 
@@ -2881,6 +2931,8 @@ static void yaffs_BlockBecameDirty(yaffs
 		(TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
 		blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
 
+	yaffs_ClearOldestDirtySequence(dev,bi);
+
 	bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
 
 	if (!bi->needsRetiring) {
@@ -3753,6 +3805,8 @@ void yaffs_DeleteChunk(yaffs_Device *dev
 			 chunkId));
 
 	bi = yaffs_GetBlockInfo(dev, block);
+	
+	yaffs_UpdateOldestDirtySequence(dev,bi);
 
 	T(YAFFS_TRACE_DELETION,
 	  (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));