Dynamically update the oldest dirty sequence number so that it does not have to be...
authorcharles <charles>
Sun, 7 Mar 2010 22:07:03 +0000 (22:07 +0000)
committercharles <charles>
Sun, 7 Mar 2010 22:07:03 +0000 (22:07 +0000)
yaffs_guts.c

index fd3d636..60227df 100644 (file)
@@ -12,7 +12,7 @@
  */
 
 const char *yaffs_guts_c_version =
  */
 
 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"
 
 #include "yportenv.h"
 #include "yaffs_trace.h"
@@ -1047,6 +1047,75 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
        return chunk;
 }
 
        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.
  */
 /*
  * Block retiring for handling a broken block.
  */
@@ -1056,6 +1125,8 @@ static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND)
        yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
 
        yaffs_InvalidateCheckpoint(dev);
        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) {
 
        if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) {
                if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) {
@@ -2665,9 +2736,6 @@ static void yaffs_DeinitialiseBlocks(yaffs_Device *dev)
 static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
                                        yaffs_BlockInfo *bi)
 {
 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. */
 
        if (!dev->param.isYaffs2)
                return 1;       /* disqualification only applies to yaffs2. */
@@ -2675,23 +2743,7 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
        if (!bi->hasShrinkHeader)
                return 1;       /* can gc */
 
        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.
 
        /* 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_FindBlockForGarbageCollection(yaffs_Device *dev,
                   dev->param.nChunksPerBlock - pagesInUse, prioritised));
        }
 
                   dev->param.nChunksPerBlock - pagesInUse, prioritised));
        }
 
-       dev->oldestDirtySequence = 0;
-
        if (dirtiest > 0)
                dev->nonAggressiveSkip = 4;
 
        if (dirtiest > 0)
                dev->nonAggressiveSkip = 4;
 
@@ -2881,6 +2931,8 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo)
                (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
                blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
 
                (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) {
        bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
 
        if (!bi->needsRetiring) {
@@ -3753,6 +3805,8 @@ void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn)
                         chunkId));
 
        bi = yaffs_GetBlockInfo(dev, block);
                         chunkId));
 
        bi = yaffs_GetBlockInfo(dev, block);
+       
+       yaffs_UpdateOldestDirtySequence(dev,bi);
 
        T(YAFFS_TRACE_DELETION,
          (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));
 
        T(YAFFS_TRACE_DELETION,
          (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));