*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.118 2010-03-12 01:22:48 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.120 2010-03-15 23:10:34 charles Exp $";
#include "yportenv.h"
#include "yaffs_trace.h"
{
int i;
__u32 seq;
- yaffs_BlockInfo *b = 0;
+ yaffs_BlockInfo *b;
if(!dev->param.isYaffs2)
return 0;
/* Find the oldest dirty sequence number. */
seq = dev->sequenceNumber;
+ b = dev->blockInfo;
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;
+ b++;
}
return seq;
}
*/
dev->refreshSkip = dev->param.refreshPeriod;
dev->refreshCount++;
-
+ bi = dev->blockInfo;
for (b = dev->internalStartBlock; b <=dev->internalEndBlock; b++){
- bi = yaffs_GetBlockInfo(dev, b);
-
-
if (bi->blockState == YAFFS_BLOCK_STATE_FULL){
if(oldest < 1 ||
oldestSequence = bi->sequenceNumber;
}
}
+ bi++;
}
if (oldest > 0) {
/* First let's see if we need to grab a prioritised block */
if (dev->hasPendingPrioritisedGCs) {
+ bi = dev->blockInfo;
for (i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++) {
- bi = yaffs_GetBlockInfo(dev, i);
- /* yaffs_VerifyBlock(dev,bi,i); */
-
if (bi->gcPrioritise) {
pendingPrioritisedExist = 1;
if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
aggressive = 1; /* Fool the non-aggressive skip logiv below */
}
}
+ bi++;
}
if (!pendingPrioritisedExist) /* None found, so we can clear this */
bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
+ /* If this is the block being garbage collected then stop gc'ing this block */
+ if(blockNo == dev->gcBlock)
+ dev->gcBlock = -1;
+
if (!bi->needsRetiring) {
yaffs_InvalidateCheckpoint(dev);
erasedOk = yaffs_EraseBlockInNAND(dev, blockNo);
bi->hasShrinkHeader = 0; /* clear the flag so that the block can erase */
- /* Take off the number of soft deleted entries because
- * they're going to get really deleted during GC.
- */
- if(dev->gcChunk == 0) /* first time through for this block */
- dev->nFreeChunks -= bi->softDeletions;
-
dev->isDoingGC = 1;
if (isCheckpointBlock ||
* No need to copy this, just forget about it and
* fix up the object.
*/
+
+ /* Free chunks already includes softdeleted chunks.
+ * How ever this chunk is going to soon be really deleted
+ * which will increment free chunks.
+ * We have to decrement free chunks so this works out properly.
+ */
+ dev->nFreeChunks--;
object->nDataChunks--;
- /* If the gc completed then clear the current gcBlock so that we find another. */
- if (bi->blockState != YAFFS_BLOCK_STATE_COLLECTING) {
+ if (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
+ /*
+ * The gc did not complete. Set block state back to FULL
+ * because checkpointing does not restore gc.
+ */
+ bi->blockState = YAFFS_BLOCK_STATE_FULL;
+ } else {
+ /* The gc completed. */
chunksAfter = yaffs_GetErasedChunks(dev);
if (chunksBefore >= chunksAfter) {
T(YAFFS_TRACE_GC,
int checkpointBlockAdjust;
+ if(dev->param.gcControl &&
+ (dev->param.gcControl(dev) & 1) == 0)
+ return YAFFS_OK;
+
if (dev->isDoingGC) {
/* Bail out so we don't get recursive gc */
return YAFFS_OK;
int retVal;
int immediateDeletion = 0;
+ yaffs_Device *dev = in->myDev;
if (!in->myInode)
immediateDeletion = 1;
in->objectId));
in->deleted = 1;
in->myDev->nDeletedFiles++;
- if (1 || in->myDev->param.isYaffs2)
+ if (dev->param.disableSoftDelete || dev->param.isYaffs2)
yaffs_ResizeFile(in, 0);
yaffs_SoftDeleteFile(in);
} else {
{
int retVal = YAFFS_OK;
int deleted = in->deleted;
+ yaffs_Device *dev = in->myDev;
- yaffs_ResizeFile(in, 0);
+ if (dev->param.disableSoftDelete || dev->param.isYaffs2)
+ yaffs_ResizeFile(in, 0);
if (in->nDataChunks > 0) {
/* Use soft deletion if there is data in the file.
dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
/* Scan all the blocks to determine their state */
+ bi = dev->blockInfo;
for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
- bi = yaffs_GetBlockInfo(dev, blk);
yaffs_ClearChunkBits(dev, blk);
bi->pagesInUse = 0;
bi->softDeletions = 0;
dev->nErasedBlocks++;
dev->nFreeChunks += dev->param.nChunksPerBlock;
}
+ bi++;
}
startIterator = dev->internalStartBlock;
chunkData = yaffs_GetTempBuffer(dev, __LINE__);
/* Scan all the blocks to determine their state */
+ bi = dev->blockInfo;
for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
- bi = yaffs_GetBlockInfo(dev, blk);
yaffs_ClearChunkBits(dev, blk);
bi->pagesInUse = 0;
bi->softDeletions = 0;
}
}
+ bi++;
}
T(YAFFS_TRACE_SCAN,
static int yaffs_CountFreeChunks(yaffs_Device *dev)
{
- int nFree;
+ int nFree=0;
int b;
yaffs_BlockInfo *blk;
- for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock;
- b++) {
- blk = yaffs_GetBlockInfo(dev, b);
-
+ blk = dev->blockInfo;
+ for (b = dev->internalStartBlock; b <= dev->internalEndBlock; b++) {
switch (blk->blockState) {
case YAFFS_BLOCK_STATE_EMPTY:
case YAFFS_BLOCK_STATE_ALLOCATING:
default:
break;
}
+ blk++;
}
return nFree;