changeset 131:99e93a234aba

Fix some checkpoint stuff, add qsort
author charles <charles>
date Sun, 21 May 2006 09:39:12 +0000
parents 2f8d5c914150
children f0d1a05787e4
files direct/Makefile direct/dtest.c direct/yaffscfg2k.c direct/ydirectenv.h yaffs_checkptrw.c yaffs_fs.c yaffs_guts.c yportenv.h
diffstat 8 files changed, 202 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/direct/Makefile
+++ b/direct/Makefile
@@ -10,7 +10,7 @@
 #
 # NB Warning this Makefile does not include header dependencies.
 #
-# $Id: Makefile,v 1.9 2006-05-08 10:13:34 charles Exp $
+# $Id: Makefile,v 1.10 2006-05-21 09:39:12 charles Exp $
 
 EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
 
@@ -22,7 +22,7 @@ CFLAGS =    -Wall -DCONFIG_YAFFS_DIRECT 
 DIRECTTESTOBJS = dtest.o yaffscfg2k.o yaffs_ecc.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
 		 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
 		 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
-		 yaffs_checkptrw.o \
+		 yaffs_checkptrw.o  yaffs_qsort.o \
 #		 yaffs_checkptrwtest.o\
 		 
 
@@ -35,7 +35,8 @@ ALLOBJS = $(DIRECTTESTOBJS) $(BOOTTESTOB
 SYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
           yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h  yaffs_nandemul2k.h \
           yaffs_nand.c yaffs_nand.h \
-          yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c
+          yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
+          yaffs_qsort.c yaffs_qsort.h
 
 #all: directtest2k boottest
 
--- a/direct/dtest.c
+++ b/direct/dtest.c
@@ -1723,7 +1723,7 @@ void multi_mount_test(const char *mountp
 
 		write_200k_file(b,"","");
 		
-		printf("######## Iteration %d   Start\n",i);
+		printf("######## Iteration %d   End\n",i);
 		dump_directory_tree(mountpt);
 		
 		yaffs_unmount(mountpt);
@@ -1731,6 +1731,58 @@ void multi_mount_test(const char *mountp
 }
 
 
+void yaffs_touch(const char *fn)
+{
+	yaffs_chmod(fn, S_IREAD | S_IWRITE);
+}
+
+void checkpoint_fill_test(const char *mountpt,int nmounts)
+{
+
+	char a[50];
+	char b[50];
+	char c[50];
+	
+	int i;
+	int j;
+	int h;
+	
+	sprintf(a,"%s/a",mountpt);
+	
+
+	
+	
+	yaffs_StartUp();
+	
+	for(i = 0; i < nmounts; i++){
+		printf("############### Iteration %d   Start\n",i);
+		yaffs_mount(mountpt);
+		dump_directory_tree(mountpt);
+		yaffs_mkdir(a,0);
+		
+		sprintf(b,"%s/zz",a);
+		
+		h = yaffs_open(b,O_CREAT | O_RDWR,S_IREAD |S_IWRITE);
+		
+		
+		while(yaffs_write(h,c,50) == 50){}
+		
+		yaffs_close(h);
+		
+		for(j = 0; j < 100; j++){
+			printf("touch %d\n",j);
+			yaffs_touch(b);
+			yaffs_unmount(mountpt);
+			yaffs_mount(mountpt);
+		}
+
+		dump_directory_tree(mountpt);		
+		yaffs_unmount(mountpt);
+	}
+}
+
+
+
 int main(int argc, char *argv[])
 {
 	//return long_test(argc,argv);
@@ -1747,7 +1799,8 @@ int main(int argc, char *argv[])
 	 
 	 //scan_pattern_test("/flash",10000,10);
 	//short_scan_test("/flash/flash",40000,200);
-	 multi_mount_test("/flash/flash",20);
+	 //multi_mount_test("/flash/flash",20);
+	 checkpoint_fill_test("/flash/flash",20);
 
 
 	
--- a/direct/yaffscfg2k.c
+++ b/direct/yaffscfg2k.c
@@ -125,11 +125,12 @@ int yaffs_StartUp(void)
 	flashDev.nBytesPerChunk = 2048;
 	flashDev.nChunksPerBlock = 64;
 	flashDev.nReservedBlocks = 5;
+	flashDev.nCheckpointReservedBlocks = 5;
 	//flashDev.checkpointStartBlock = 1;
 	//flashDev.checkpointEndBlock = 20;
 	flashDev.startBlock = 20; 
-	//flashDev.endBlock = 127; // Last block in 16MB
-	flashDev.endBlock = yflash_GetNumberOfBlocks()-1;
+	flashDev.endBlock = 127; // Make it smaller
+	//flashDev.endBlock = yflash_GetNumberOfBlocks()-1;
 	flashDev.isYaffs2 = 1;
 	flashDev.wideTnodesDisabled=0;
 	flashDev.nShortOpCaches = 10; // Use caches
--- a/direct/ydirectenv.h
+++ b/direct/ydirectenv.h
@@ -14,7 +14,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
- * $Id: ydirectenv.h,v 1.2 2005-10-07 03:48:50 charles Exp $
+ * $Id: ydirectenv.h,v 1.3 2006-05-21 09:39:12 charles Exp $
  *
  */
  
@@ -46,6 +46,11 @@
 #define YMALLOC_ALT(x) malloc(x)
 #define YFREE_ALT(x)   free(x)
 
+#define YMALLOC_DMA(x) malloc(x)
+
+#define YYIELD()  do {} while(0)
+
+
 
 //#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s))
 //#define YALERT(s) YINFO(s)
--- a/yaffs_checkptrw.c
+++ b/yaffs_checkptrw.c
@@ -13,7 +13,7 @@
  */
 
 const char *yaffs_checkptrw_c_version =
-    "$Id: yaffs_checkptrw.c,v 1.2 2006-05-17 09:31:07 charles Exp $";
+    "$Id: yaffs_checkptrw.c,v 1.3 2006-05-21 09:39:12 charles Exp $";
 
 
 #include "yaffs_checkptrw.h"
@@ -24,16 +24,12 @@ static int yaffs_CheckpointSpaceOk(yaffs
 
 	int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
 	
-	if(blocksAvailable < 0)
-		blocksAvailable = 0;
-		
-	T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpt blocks available" TENDSTR)));
+	T(YAFFS_TRACE_CHECKPOINT,
+		(TSTR("checkpt blocks available = %d" TENDSTR),
+		blocksAvailable));
 		
 	
-	if(blocksAvailable <= 0)
-		return 0;
-	   	
-	return 1;
+	return (blocksAvailable <= 0) ? 0 : 1;
 }
 
 
@@ -167,6 +163,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
 		dev->checkpointByteOffset = dev->nBytesPerChunk;
 		/* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully)
 		 * going to be way more than we need */
+		dev->blocksInCheckpoint = 0;
 		dev->checkpointMaxBlocks = (dev->endBlock - dev->startBlock)/16 + 2;
 		dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks);
 		for(i = 0; i < dev->checkpointMaxBlocks; i++)
--- a/yaffs_fs.c
+++ b/yaffs_fs.c
@@ -31,7 +31,7 @@
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.47 2006-05-17 09:36:06 charles Exp $";
+    "$Id: yaffs_fs.c,v 1.48 2006-05-21 09:39:12 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/config.h>
@@ -1547,6 +1547,8 @@ static struct super_block *yaffs_interna
 		dev->nBytesPerChunk = mtd->oobblock;
 		dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
 		nBlocks = mtd->size / mtd->erasesize;
+
+		dev->nCheckpointReservedBlocks = 10;
 		dev->startBlock = 0;
 		dev->endBlock = nBlocks - 1;
 	} else {
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -13,7 +13,7 @@
  */
 
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.33 2006-05-17 09:20:26 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.34 2006-05-21 09:39:12 charles Exp $";
 
 #include "yportenv.h"
 
@@ -22,6 +22,9 @@ const char *yaffs_guts_c_version =
 #include "yaffs_tagsvalidity.h"
 
 #include "yaffs_tagscompat.h"
+#ifndef CONFIG_YAFFS_OWN_SORT
+#include "yaffs_qsort.h"
+#endif
 #include "yaffs_nand.h"
 
 #include "yaffs_checkptrw.h"
@@ -166,6 +169,32 @@ static void yaffs_ReleaseTempBuffer(yaff
 }
 
 /*
+ * Determine if we have a managed buffer.
+ */
+int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer)
+{
+	int i;
+	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+		if (dev->tempBuffer[i].buffer == buffer)
+			return 1;
+
+	}
+
+    for (i = 0; i < dev->nShortOpCaches; i++) {
+        if( dev->srCache[i].data == buffer )
+            return 1;
+
+    }
+
+    if (buffer == dev->checkpointBuffer)
+      return 1;
+
+    T(YAFFS_TRACE_ALWAYS,
+	  (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR)));
+    return 0;
+}
+
+/*
  * Chunk bitmap manipulations
  */
 
@@ -1722,6 +1751,15 @@ int yaffs_RenameObject(yaffs_Object * ol
 #endif
 
 	obj = yaffs_FindObjectByName(oldDir, oldName);
+	/* Check new name to long. */
+	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
+	    yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
+	  /* ENAMETOOLONG */
+	  return YAFFS_FAIL;
+	else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
+		 yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
+	  /* ENAMETOOLONG */
+	  return YAFFS_FAIL;
 
 	if (obj && obj->renameAllowed) {
 
@@ -2336,6 +2374,8 @@ static int yaffs_CheckGarbageCollection(
 	int aggressive;
 	int gcOk = YAFFS_OK;
 	int maxTries = 0;
+	
+	int checkpointBlockAdjust;
 
 	if (dev->isDoingGC) {
 		/* Bail out so we don't get recursive gc */
@@ -2348,7 +2388,12 @@ static int yaffs_CheckGarbageCollection(
 
 	do {
 		maxTries++;
-		if (dev->nErasedBlocks < dev->nReservedBlocks) {
+		
+		checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
+		if(checkpointBlockAdjust < 0)
+			checkpointBlockAdjust = 0;
+
+		if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) {
 			/* We need a block soon...*/
 			aggressive = 1;
 		} else {
@@ -3382,13 +3427,15 @@ static int yaffs_CheckpointTnodeWorker(y
 {
 	int i;
 	yaffs_Device *dev = in->myDev;
+	int ok = 1;
+	int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
 
 	if (tn) {
 		if (level > 0) {
 
-			for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++){
+			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){
 				if (tn->internal[i]) {
-					yaffs_CheckpointTnodeWorker(in,
+					ok = yaffs_CheckpointTnodeWorker(in,
 							tn->internal[i],
 							level - 1,
 							(chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
@@ -3397,12 +3444,13 @@ static int yaffs_CheckpointTnodeWorker(y
 		} else if (level == 0) {
 			__u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
 			/* printf("write tnode at %d\n",baseOffset); */
-			yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset));
-			yaffs_CheckpointWrite(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
+			ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
+			if(ok)
+				ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
 		}
 	}
 
-	return 1;
+	return ok;
 
 }
 
@@ -3519,13 +3567,13 @@ static int yaffs_ReadCheckpointObjects(y
 			
 		if(ok && cp.objectId == ~0)
 			done = 1;
-		else {
+		else if(ok){
 			/* printf("Read object %d type %d\n",cp.objectId,cp.variantType); */
 			obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
 			if(obj) {
 				yaffs_CheckpointObjectToObject(obj,&cp);
 				if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
-					yaffs_ReadCheckpointTnodes(obj);
+					ok = yaffs_ReadCheckpointTnodes(obj);
 				} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
 					obj->hardLinks.next =
 						    (struct list_head *)
@@ -3559,12 +3607,13 @@ static int yaffs_WriteCheckpointData(yaf
 	if(ok)
 		ok = yaffs_WriteCheckpointValidityMarker(dev,0);
 		
-	yaffs_CheckpointClose(dev);
-		
-//	if(dev->checkpointBytes)
+	if(!yaffs_CheckpointClose(dev))
+		 ok = 0;
+		 
+	if(ok)
 	    	dev->isCheckpointed = 1;
-//	 else 
-	 	//dev->isCheckpointed = 0;
+	 else 
+	 	dev->isCheckpointed = 0;
 
 	return dev->isCheckpointed;
 }
@@ -3586,12 +3635,13 @@ static int yaffs_ReadCheckpointData(yaff
 		
 
 
-	yaffs_CheckpointClose(dev);
-
-//	if(ok)
+	if(!yaffs_CheckpointClose(dev))
+		ok = 0;
+
+	if(ok)
 	    	dev->isCheckpointed = 1;
-//	 else 
-//	 	dev->isCheckpointed = 0;
+	 else 
+	 	dev->isCheckpointed = 0;
 
 	return ok ? 1 : 0;
 
@@ -3599,7 +3649,8 @@ static int yaffs_ReadCheckpointData(yaff
 
 static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
 {
-	if(dev->isCheckpointed){
+	if(dev->isCheckpointed || 
+	   dev->blocksInCheckpoint > 0){
 		dev->isCheckpointed = 0;
 		yaffs_CheckpointInvalidateStream(dev);
 		if(dev->superBlock && dev->markSuperBlockDirty)
@@ -3610,16 +3661,26 @@ static void yaffs_InvalidateCheckpoint(y
 
 int yaffs_CheckpointSave(yaffs_Device *dev)
 {
+	T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
 	if(!dev->isCheckpointed)
 		yaffs_WriteCheckpointData(dev);
 	
+	T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+
 	return dev->isCheckpointed;
 }
 
 int yaffs_CheckpointRestore(yaffs_Device *dev)
 {
+	int retval;
+	T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
 	
-	return yaffs_ReadCheckpointData(dev);
+	retval = yaffs_ReadCheckpointData(dev);
+
+	T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+	
+	return retval;
 }
 
 /*--------------------- File read/write ------------------------
@@ -4378,6 +4439,18 @@ static void yaffs_HardlinkFixup(yaffs_De
 
 
 
+static int ybicmp(const void *a, const void *b){
+    register int aseq = ((yaffs_BlockIndex *)a)->seq;
+    register int bseq = ((yaffs_BlockIndex *)b)->seq;
+    register int ablock = ((yaffs_BlockIndex *)a)->block;
+    register int bblock = ((yaffs_BlockIndex *)b)->block;
+    if( aseq == bseq )
+        return ablock - bblock;
+    else
+        return aseq - bseq;
+
+}
+
 static int yaffs_Scan(yaffs_Device * dev)
 {
 	yaffs_ExtendedTags tags;
@@ -5004,11 +5077,23 @@ static int yaffs_ScanBackwards(yaffs_Dev
 		}
 	}
 
-	/*
-	 * Sort the blocks
-	 * Dungy old bubble sort for now...
-	 */
+	T(YAFFS_TRACE_SCAN,
+	(TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan));
+
+
+
+	YYIELD();
+
+	/* Sort the blocks */
+#ifndef CONFIG_YAFFS_USE_OWN_SORT
 	{
+		/* Use qsort now. */
+		qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
+	}
+#else
+	{
+	 	/* Dungy old bubble sort... */
+	 	
 		yaffs_BlockIndex temp;
 		int i;
 		int j;
@@ -5021,6 +5106,11 @@ static int yaffs_ScanBackwards(yaffs_Dev
 					blockIndex[i] = temp;
 				}
 	}
+#endif
+
+	YYIELD();
+
+    	T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));
 
 	/* Now scan the blocks looking at the data. */
 	startIterator = 0;
@@ -5031,6 +5121,9 @@ static int yaffs_ScanBackwards(yaffs_Dev
 	/* For each block.... backwards */
 	for (blockIterator = endIterator; blockIterator >= startIterator;
 	     blockIterator--) {
+	        /* Cooperative multitasking! This loop can run for so
+		   long that watchdog timers expire. */
+	        YYIELD();
 
 		/* get the block to scan in the correct order */
 		blk = blockIndex[blockIterator].block;
@@ -6074,7 +6167,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
 		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
 			dev->tempBuffer[i].line = 0;	/* not in use */
 			dev->tempBuffer[i].buffer =
-			    YMALLOC(dev->nBytesPerChunk);
+			    YMALLOC_DMA(dev->nBytesPerChunk);
 		}
 	}
 	
@@ -6092,7 +6185,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
 			dev->srCache[i].object = NULL;
 			dev->srCache[i].lastUse = 0;
 			dev->srCache[i].dirty = 0;
-			dev->srCache[i].data = YMALLOC(dev->nBytesPerChunk);
+			dev->srCache[i].data = YMALLOC_DMA(dev->nBytesPerChunk);
 		}
 		dev->srLastUse = 0;
 	}
--- a/yportenv.h
+++ b/yportenv.h
@@ -15,7 +15,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
- * $Id: yportenv.h,v 1.10 2006-05-08 10:13:34 charles Exp $
+ * $Id: yportenv.h,v 1.11 2006-05-21 09:39:12 charles Exp $
  *
  */
 
@@ -58,6 +58,10 @@
 #define YFREE(x)   kfree(x)
 #define YMALLOC_ALT(x) vmalloc(x)
 #define YFREE_ALT(x)   vfree(x)
+#define YMALLOC_DMA(x) YMALLOC(x)
+
+// KR - added for use in scan so processes aren't blocked indefinitely.
+#define YYIELD() schedule()
 
 #define YAFFS_ROOT_MODE				0666
 #define YAFFS_LOSTNFOUND_MODE		0666