changeset 203:88a05fb266f0

Change checkpoint to calculate number of blocks required instead of using a hardcoded value
author charles
date Mon, 03 Dec 2007 03:21:48 +0000
parents 8bfa3820f9cb
children 5ee93b08ed3a
files Kconfig direct/yaffscfg.c direct/yaffscfg2k.c yaffs_fs.c yaffs_guts.c yaffs_guts.h
diffstat 6 files changed, 74 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/Kconfig
+++ b/Kconfig
@@ -110,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD
 
 	  If unsure, say N.
 
-config YAFFS_CHECKPOINT_RESERVED_BLOCKS
-	int "Reserved blocks for checkpointing"
-	depends on YAFFS_YAFFS2
-	default 10
-	help
-          Give the number of Blocks to reserve for checkpointing.
-	  Checkpointing saves the state at unmount so that mounting is
-	  much faster as a scan of all the flash to regenerate this state
-	  is not needed.  These Blocks are reserved per partition, so if
-	  you have very small partitions the default (10) may be a mess
-	  for you.  You can set this value to 0, but that does not mean
-	  checkpointing is disabled at all. There only won't be any
-	  specially reserved blocks for checkpointing, so if there is
-	  enough free space on the filesystem, it will be used for
-	  checkpointing.
-
-	  If unsure, leave at default (10), but don't wonder if there are
-	  always 2MB used on your large page device partition (10 x 2k
-	  pagesize). When using small partitions or when being very small
-	  on space, you probably want to set this to zero.
 
 config YAFFS_DISABLE_WIDE_TNODES
 	bool "Turn off wide tnodes"
--- a/direct/yaffscfg.c
+++ b/direct/yaffscfg.c
@@ -93,7 +93,7 @@ int yaffs_StartUp(void)
 	// Set up devices
 
 	// /ram
-	ramDev.nBytesPerChunk = 512;
+	ramDev.nDataBytesPerChunk = 512;
 	ramDev.nChunksPerBlock = 32;
 	ramDev.nReservedBlocks = 2; // Set this smaller for RAM
 	ramDev.startBlock = 1; // Can't use block 0
@@ -107,7 +107,7 @@ int yaffs_StartUp(void)
 	ramDev.initialiseNAND = yramdisk_InitialiseNAND;
 
 	// /boot
-	bootDev.nBytesPerChunk = 612;
+	bootDev.nDataBytesPerChunk = 512;
 	bootDev.nChunksPerBlock = 32;
 	bootDev.nReservedBlocks = 5;
 	bootDev.startBlock = 1; // Can't use block 0
@@ -121,7 +121,7 @@ int yaffs_StartUp(void)
 	bootDev.initialiseNAND = yflash_InitialiseNAND;
 
 		// /flash
-	flashDev.nBytesPerChunk =  512;
+	flashDev.nDataBytesPerChunk =  512;
 	flashDev.nChunksPerBlock = 32;
 	flashDev.nReservedBlocks = 5;
 	flashDev.startBlock = 128; // First block after 2MB
--- a/direct/yaffscfg2k.c
+++ b/direct/yaffscfg2k.c
@@ -176,7 +176,6 @@ int yaffs_StartUp(void)
 	flashDev.nDataBytesPerChunk = 2048;
 	flashDev.nChunksPerBlock = 64;
 	flashDev.nReservedBlocks = 5;
-	flashDev.nCheckpointReservedBlocks = 5;
 	//flashDev.checkpointStartBlock = 1;
 	//flashDev.checkpointEndBlock = 20;
 	flashDev.startBlock = 0;
@@ -224,6 +223,6 @@ int yaffs_StartUp(void)
 
 void SetCheckpointReservedBlocks(int n)
 {
-	flashDev.nCheckpointReservedBlocks = n;
+//	flashDev.nCheckpointReservedBlocks = n;
 }
 
--- a/yaffs_fs.c
+++ b/yaffs_fs.c
@@ -1807,7 +1807,6 @@ static struct super_block *yaffs_interna
 #endif
 		nBlocks = mtd->size / mtd->erasesize;
 
-		dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;
 		dev->startBlock = 0;
 		dev->endBlock = nBlocks - 1;
 	} else {
@@ -1995,7 +1994,6 @@ static char *yaffs_dump_dev(char *buf, y
 	buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
 	buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
 	buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks);
-	buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks);
 	buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);
 	buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
 	buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -1146,6 +1146,10 @@ static int yaffs_CreateTnodes(yaffs_Devi
 	 * Must be a multiple of 32-bits  */
 	tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
 
+	if(tnodeSize < sizeof(yaffs_Tnode))
+		tnodeSize = sizeof(yaffs_Tnode);
+		
+
 	/* make these things */
 
 	newTnodes = YMALLOC(nTnodes * tnodeSize);
@@ -1236,15 +1240,21 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya
 		dev->nFreeTnodes--;
 	}
 
+	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
+
 	return tn;
 }
 
 static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
 {
 	yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
+	int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+
+	if(tnodeSize < sizeof(yaffs_Tnode))
+		tnodeSize = sizeof(yaffs_Tnode);
 	
 	if(tn)
-		memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+		memset(tn, 0, tnodeSize);
 
 	return tn;	
 }
@@ -1265,6 +1275,8 @@ static void yaffs_FreeTnode(yaffs_Device
 		dev->freeTnodes = tn;
 		dev->nFreeTnodes++;
 	}
+	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
+	
 }
 
 static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
@@ -1909,6 +1921,8 @@ static yaffs_Object *yaffs_AllocateEmpty
 			yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
 		}
 	}
+	
+	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 
 	return tn;
 }
@@ -1970,6 +1984,9 @@ static void yaffs_FreeObject(yaffs_Objec
 	tn->siblings.next = (struct list_head *)(dev->freeObjects);
 	dev->freeObjects = tn;
 	dev->nFreeObjects++;
+
+	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
+
 }
 
 #ifdef __KERNEL__
@@ -2804,6 +2821,40 @@ static int yaffs_FindBlockForAllocation(
 }
 
 
+
+static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
+{
+	if(!dev->nCheckpointBlocksRequired){
+		/* Not a valid value so recalculate */
+		int nBytes = 0;
+		int nBlocks;
+		int devBlocks = (dev->endBlock - dev->startBlock + 1);
+		int tnodeSize;
+
+		tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+
+		if(tnodeSize < sizeof(yaffs_Tnode))
+			tnodeSize = sizeof(yaffs_Tnode);
+		
+		nBytes += sizeof(yaffs_CheckpointValidity);
+		nBytes += sizeof(yaffs_CheckpointDevice);
+		nBytes += devBlocks * sizeof(yaffs_BlockInfo);
+		nBytes += devBlocks * dev->chunkBitmapStride;
+		nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects);
+		nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes);
+		nBytes += sizeof(yaffs_CheckpointValidity);
+		nBytes += sizeof(__u32); /* checksum*/
+	
+		/* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
+	
+		nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3;
+	
+		dev->nCheckpointBlocksRequired = nBlocks;
+	}
+
+	return dev->nCheckpointBlocksRequired;
+}
+
 // Check if there's space to allocate...
 // Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
 static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
@@ -2812,7 +2863,7 @@ static int yaffs_CheckSpaceForAllocation
 	int reservedBlocks = dev->nReservedBlocks;
 	int checkpointBlocks;
 	
-	checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
+	checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
 	if(checkpointBlocks < 0)
 		checkpointBlocks = 0;
 	
@@ -3145,7 +3196,7 @@ static int yaffs_CheckGarbageCollection(
 	do {
 		maxTries++;
 		
-		checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
+		checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
 		if(checkpointBlockAdjust < 0)
 			checkpointBlockAdjust = 0;
 
@@ -4223,7 +4274,11 @@ static int yaffs_CheckpointTnodeWorker(y
 	int i;
 	yaffs_Device *dev = in->myDev;
 	int ok = 1;
-	int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+	int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+
+	if(tnodeSize < sizeof(yaffs_Tnode))
+		tnodeSize = sizeof(yaffs_Tnode);
+	
 
 	if (tn) {
 		if (level > 0) {
@@ -4241,7 +4296,7 @@ static int yaffs_CheckpointTnodeWorker(y
 			/* printf("write tnode at %d\n",baseOffset); */
 			ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
 			if(ok)
-				ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
+				ok = (yaffs_CheckpointWrite(dev,tn,tnodeSize) == tnodeSize);
 		}
 	}
 
@@ -4275,7 +4330,11 @@ static int yaffs_ReadCheckpointTnodes(ya
 	yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
 	yaffs_Tnode *tn;
 	int nread = 0;
-	
+	int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+
+	if(tnodeSize < sizeof(yaffs_Tnode))
+		tnodeSize = sizeof(yaffs_Tnode);
+
 	ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
 	
 	while(ok && (~baseChunk)){
@@ -4286,8 +4345,7 @@ static int yaffs_ReadCheckpointTnodes(ya
 		/* printf("read  tnode at %d\n",baseChunk); */
 		tn = yaffs_GetTnodeRaw(dev);
 		if(tn)
-			ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
-			      (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+			ok = (yaffs_CheckpointRead(dev,tn,tnodeSize) == tnodeSize);
 		else
 			ok = 0;
 			
@@ -7415,7 +7473,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
 	nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
 	
 	/* Now we figure out how much to reserve for the checkpoint and report that... */
-	blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
+	blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
 	if(blocksForCheckpoint < 0)
 		blocksForCheckpoint = 0;
 		
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -544,7 +544,7 @@ struct yaffs_DeviceStruct {
 	/* Stuff used by the shared space checkpointing mechanism */
 	/* If this value is zero, then this mechanism is disabled */
 	
-	int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
+//	int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
 
 	
 
@@ -663,6 +663,8 @@ struct yaffs_DeviceStruct {
 	__u32 checkpointSum;
 	__u32 checkpointXor;
 	
+	int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */
+	
 	/* Block Info */
 	yaffs_BlockInfo *blockInfo;
 	__u8 *chunkBits;	/* bitmap of chunks in use */