X-Git-Url: http://aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=inline;f=yaffs_guts.c;h=e5b1eaf185dd410014dde4b69bf04aceb68585c7;hb=6faeadf2b9efdb9f403b2cced9317578fd984e3a;hp=e9cda9c55b6d9c60109c9b6637cfec421d013b1c;hpb=9dc68bf9810613883954fc50d26ed6f9c2c87ac0;p=yaffs2.git diff --git a/yaffs_guts.c b/yaffs_guts.c index e9cda9c..e5b1eaf 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,7 +12,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.112 2010-03-05 01:49:00 charles Exp $"; + "$Id: yaffs_guts.c,v 1.115 2010-03-07 23:43:34 charles Exp $"; #include "yportenv.h" #include "yaffs_trace.h" @@ -404,16 +404,19 @@ static int yaffs_CountChunkBits(yaffs_Device *dev, int blk) static int yaffs_SkipVerification(yaffs_Device *dev) { + dev=dev; return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); } static int yaffs_SkipFullVerification(yaffs_Device *dev) { + dev=dev; return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL)); } static int yaffs_SkipNANDVerification(yaffs_Device *dev) { + dev=dev; return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); } @@ -1044,6 +1047,80 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, 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; + + if(!dev->param.isYaffs2) + return 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->param.isYaffs2 && !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(!dev->param.isYaffs2) + return; + + 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->param.isYaffs2 && dev->oldestDirtySequence){ + if(dev->oldestDirtySequence > bi->sequenceNumber) + dev->oldestDirtySequence = bi->sequenceNumber; + } +} + /* * Block retiring for handling a broken block. */ @@ -1053,6 +1130,8 @@ static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND) 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) { @@ -1094,11 +1173,18 @@ static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *tags) { + dev=dev; + chunkInNAND=chunkInNAND; + data=data; + tags=tags; } static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, const yaffs_ExtendedTags *tags) { + dev=dev; + chunkInNAND=chunkInNAND; + tags=tags; } void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi) @@ -1446,6 +1532,8 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, int requiredTallness; int level = fStruct->topLevel; + dev=dev; + /* Check sane level and chunk Id */ if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) return NULL; @@ -1715,6 +1803,7 @@ static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk) if (theBlock) { theBlock->softDeletions++; dev->nFreeChunks++; + yaffs_UpdateOldestDirtySequence(dev,theBlock); } } @@ -2653,9 +2742,6 @@ static void yaffs_DeinitialiseBlocks(yaffs_Device *dev) 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. */ @@ -2663,23 +2749,7 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, 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. @@ -2847,8 +2917,6 @@ static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, dev->param.nChunksPerBlock - pagesInUse, prioritised)); } - dev->oldestDirtySequence = 0; - if (dirtiest > 0) dev->nonAggressiveSkip = 4; @@ -2869,6 +2937,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" : "")); + yaffs_ClearOldestDirtySequence(dev,bi); + bi->blockState = YAFFS_BLOCK_STATE_DIRTY; if (!bi->needsRetiring) { @@ -3741,6 +3811,8 @@ void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn) chunkId)); bi = yaffs_GetBlockInfo(dev, block); + + yaffs_UpdateOldestDirtySequence(dev,bi); T(YAFFS_TRACE_DELETION, (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));