changeset 102:c62ef0c1e49d

Wide tnode support
author charles <charles>
date Wed, 07 Dec 2005 21:49:18 +0000
parents 718723547ec0
children a3aac8938f90
files direct/dtest.c direct/yaffs_fileem2k.h direct/yaffscfg2k.c yaffs_guts.c yaffs_guts.h yaffs_mtdif2.c
diffstat 6 files changed, 189 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/direct/dtest.c
+++ b/direct/dtest.c
@@ -1390,6 +1390,56 @@ void freespace_test(const char *mountpt)
 	
 }
 
+void simple_rw_test(const char *mountpt)
+{
+	int i;
+	int h;
+	char a[100];
+	
+	int x;
+	int result;
+
+	sprintf(a,"%s/aaa",mountpt);
+	
+	yaffs_StartUp();
+	
+	yaffs_mount(mountpt);
+	
+	yaffs_unlink(a);
+	
+	h = yaffs_open(a,O_CREAT| O_TRUNC | O_RDWR, S_IREAD | S_IWRITE);
+	
+	for(i = 100000;i < 200000; i++){
+		result = yaffs_write(h,&i,sizeof(i));
+		
+		if(result != 4)
+		{
+			printf("write error\n");
+			exit(1);
+		}
+	}
+	
+	//yaffs_close(h);
+	
+	// h = yaffs_open(a,O_RDWR, S_IREAD | S_IWRITE);
+	
+	
+	yaffs_lseek(h,0,SEEK_SET);
+	
+	for(i = 100000; i < 200000; i++){
+		result = yaffs_read(h,&x,sizeof(x));
+		
+		if(result != 4 || x != i){
+			printf("read error %d %x %x\n",i,result,x);
+		}
+	}
+	
+	printf("Simple rw test passed\n");
+	
+	
+	
+}
+
 
 void scan_deleted_files_test(const char *mountpt)
 {
@@ -1573,10 +1623,11 @@ int main(int argc, char *argv[])
 	
 	//long_test_on_path("/ram2k");
 	// long_test_on_path("/flash");
-	//fill_disk_test("/flash");
+	simple_rw_test("/flash/flash");
+	fill_disk_test("/flash/flash");
 	// rename_over_test("/flash");
 	//lookup_test("/flash");
-	freespace_test("/flash");
+	freespace_test("/flash/flash");
 	
 	
 	
--- a/direct/yaffs_fileem2k.h
+++ b/direct/yaffs_fileem2k.h
@@ -17,7 +17,7 @@
 
 #if 1
 
-#define SIZE_IN_MB 32
+#define SIZE_IN_MB 512
 #define PAGE_DATA_SIZE (2048)
 #define PAGE_SPARE_SIZE  (64)
 #define PAGE_SIZE  (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
--- a/direct/yaffscfg2k.c
+++ b/direct/yaffscfg2k.c
@@ -68,9 +68,9 @@ static yaffsfs_DeviceConfiguration yaffs
 #else
 	{ "/", &ramDev},
 	{ "/flash/boot", &bootDev},
-	{ "/flash/", &flashDev},
+	{ "/flash/flash", &flashDev},
 	{ "/ram2k", &ram2kDev},
-	{(void *)0,(void *)0}
+	{(void *)0,(void *)0} /* Null entry to terminate list */
 #endif
 };
 
@@ -129,6 +129,7 @@ int yaffs_StartUp(void)
 	//flashDev.endBlock = 127; // Last block in 16MB
 	flashDev.endBlock = yflash_GetNumberOfBlocks()-1;
 	flashDev.isYaffs2 = 1;
+	flashDev.wideTnodesDisabled=0;
 	flashDev.nShortOpCaches = 10; // Use caches
 	flashDev.genericDevice = (void *) 2;	// Used to identify the device in fstat.
 	flashDev.writeChunkWithTagsToNAND = yflash_WriteChunkWithTagsToNAND;
--- a/yaffs_guts.c
+++ b/yaffs_guts.c
@@ -13,7 +13,7 @@
  */
 
 const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.23 2005-11-07 07:19:34 charles Exp $";
+    "$Id: yaffs_guts.c,v 1.24 2005-12-07 21:49:18 charles Exp $";
 
 #include "yportenv.h"
 
@@ -538,15 +538,23 @@ static void yaffs_SetObjectName(yaffs_Ob
 static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)
 {
 	int i;
+	int tnodeSize;
 	yaffs_Tnode *newTnodes;
+	__u8 *mem;
+	yaffs_Tnode *current;
+	yaffs_Tnode *next;
 	yaffs_TnodeList *tnl;
 
 	if (nTnodes < 1)
 		return YAFFS_OK;
+		
+	/* Calculate the tnode size in bytes for variable width tnode support.
+	 * Must be a multiple of 32-bits  */
+	tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
 
 	/* make these things */
 
-	newTnodes = YMALLOC(nTnodes * sizeof(yaffs_Tnode));
+	mem = newTnodes = YMALLOC(nTnodes * tnodeSize);
 
 	if (!newTnodes) {
 		T(YAFFS_TRACE_ERROR,
@@ -555,6 +563,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
 	}
 
 	/* Hook them into the free list */
+#if 0
 	for (i = 0; i < nTnodes - 1; i++) {
 		newTnodes[i].internal[0] = &newTnodes[i + 1];
 #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
@@ -567,6 +576,21 @@ static int yaffs_CreateTnodes(yaffs_Devi
 	newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
 #endif
 	dev->freeTnodes = newTnodes;
+#else
+	/* New hookup for wide tnodes */
+	for(i = 0; i < nTnodes -1; i++) {
+		current = (yaffs_Tnode *) &mem[i * tnodeSize];
+		next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
+		current->internal[0] = next;
+	}
+	
+	current = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
+	current->internal[0] = dev->freeTnodes;
+	dev->freeTnodes = (yaffs_Tnode *)mem;
+
+#endif
+
+
 	dev->nFreeTnodes += nTnodes;
 	dev->nTnodesCreated += nTnodes;
 
@@ -615,7 +639,7 @@ static yaffs_Tnode *yaffs_GetTnode(yaffs
 		dev->freeTnodes = dev->freeTnodes->internal[0];
 		dev->nFreeTnodes--;
 		/* zero out */
-		memset(tn, 0, sizeof(yaffs_Tnode));
+		memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
 	}
 
 	return tn;
@@ -666,6 +690,64 @@ static void yaffs_InitialiseTnodes(yaffs
 
 }
 
+
+void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val)
+{
+  __u32 *map = (__u32 *)tn;
+  __u32 bitInMap;
+  __u32 bitInWord;
+  __u32 wordInMap;
+  __u32 mask;
+  
+  pos &= YAFFS_TNODES_LEVEL0_MASK;
+  val >>= dev->chunkGroupBits;
+  
+  bitInMap = pos * dev->tnodeWidth;
+  wordInMap = bitInMap /32;
+  bitInWord = bitInMap & (32 -1);
+  
+  mask = dev->tnodeMask << bitInWord;
+  
+  map[wordInMap] &= ~mask;
+  map[wordInMap] |= (mask & (val << bitInWord));
+  
+  if(dev->tnodeWidth > (32-bitInWord)) {
+    bitInWord = (32 - bitInWord);
+    wordInMap++;;
+    mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord);
+    map[wordInMap] &= ~mask;
+    map[wordInMap] |= (mask & (val >> bitInWord));
+  }
+}
+
+__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos)
+{
+  __u32 *map = (__u32 *)tn;
+  __u32 bitInMap;
+  __u32 bitInWord;
+  __u32 wordInMap;
+  __u32 val;
+  
+  pos &= YAFFS_TNODES_LEVEL0_MASK;
+  
+  bitInMap = pos * dev->tnodeWidth;
+  wordInMap = bitInMap /32;
+  bitInWord = bitInMap & (32 -1);
+  
+  val = map[wordInMap] >> bitInWord;
+  
+  if(dev->tnodeWidth > (32-bitInWord)) {
+    bitInWord = (32 - bitInWord);
+    wordInMap++;;
+    val |= (map[wordInMap] << bitInWord);
+  }
+  
+  val &= dev->tnodeMask;
+  val <<= dev->chunkGroupBits;
+  
+  return val;
+}
+
 /* ------------------- End of individual tnode manipulation -----------------*/
 
 /* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
@@ -883,16 +965,13 @@ static int yaffs_DeleteWorker(yaffs_Obje
 
 			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit;
 			     i--) {
-				if (tn->level0[i]) {
+			        theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+				if (theChunk) {
 
 					chunkInInode =
 					    (chunkOffset <<
 					     YAFFS_TNODES_LEVEL0_BITS) + i;
 
-					theChunk =
-					    tn->level0[i] << dev->
-					    chunkGroupBits;
-
 					foundChunk =
 					    yaffs_FindChunkInGroup(dev,
 								   theChunk,
@@ -914,7 +993,7 @@ static int yaffs_DeleteWorker(yaffs_Obje
 
 					}
 
-					tn->level0[i] = 0;
+					yaffs_PutLevel0Tnode(dev,tn,i,0);
 				}
 
 			}
@@ -985,17 +1064,14 @@ static int yaffs_SoftDeleteWorker(yaffs_
 		} else if (level == 0) {
 
 			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
-				if (tn->level0[i]) {
+				theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+				if (theChunk) {
 					/* Note this does not find the real chunk, only the chunk group.
 					 * We make an assumption that a chunk group is not larger than 
 					 * a block.
 					 */
-					theChunk =
-					    (tn->level0[i] << dev->
-					     chunkGroupBits);
-
 					yaffs_SoftDeleteChunk(dev, theChunk);
-					tn->level0[i] = 0;
+					yaffs_PutLevel0Tnode(dev,tn,i,0);
 				}
 
 			}
@@ -2382,9 +2458,7 @@ static int yaffs_FindChunkInFile(yaffs_O
 	tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
 
 	if (tn) {
-		theChunk =
-		    tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << 
-		    		dev->chunkGroupBits;
+		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
 
 		retVal =
 		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
@@ -2413,9 +2487,7 @@ static int yaffs_FindAndDeleteChunkInFil
 
 	if (tn) {
 
-		theChunk =
-		    tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->
-		    chunkGroupBits;
+		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
 
 		retVal =
 		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
@@ -2423,7 +2495,7 @@ static int yaffs_FindAndDeleteChunkInFil
 
 		/* Delete the entry in the filestructure (if found) */
 		if (retVal != -1) {
-			tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = 0;
+			yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0);
 		}
 	} else {
 		/*T(("No level 0 found for %d\n", chunkInInode)); */
@@ -2466,9 +2538,7 @@ static int yaffs_CheckFileSanity(yaffs_O
 
 		if (tn) {
 
-			theChunk =
-			    tn->level0[chunk & YAFFS_TNODES_LEVEL0_MASK] << in->
-			    myDev->chunkGroupBits;
+			theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk);
 
 			if (yaffs_CheckChunkBits
 			    (dev, theChunk / dev->nChunksPerBlock,
@@ -2534,7 +2604,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
 		return YAFFS_FAIL;
 	}
 
-	existingChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK];
+	existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
 
 	if (inScan != 0) {
 		/* If we're scanning then we need to test for duplicates
@@ -2613,8 +2683,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
 		in->nDataChunks++;
 	}
 
-	tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] =
-	    (chunkInNAND >> dev->chunkGroupBits);
+	yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND);
 
 	return YAFFS_OK;
 }
@@ -5408,16 +5477,33 @@ int yaffs_GutsInitialise(yaffs_Device * 
 
 	if (extraBits > 0)
 		bits++;
-
-	/* Level0 Tnodes are 16 bits, so if the bitwidth of the
+	
+	/* Set up tnode width if wide tnodes are enabled. */
+	if(!dev->wideTnodesDisabled){
+		/* bits must be even so that we end up with 32-bit words */
+		if(bits & 1)
+			bits++;
+		if(bits < 16)
+			dev->tnodeWidth = 16;
+		else
+			dev->tnodeWidth = bits;
+	}
+	else
+		dev->tnodeWidth = 16;
+ 
+	dev->tnodeMask = (1<<dev->tnodeWidth)-1;
+		
+	/* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
+	 * so if the bitwidth of the
 	 * chunk range we're using is greater than 16 we need
 	 * to figure out chunk shift and chunkGroupSize
 	 */
-	if (bits <= 16) {
+		 
+	if (bits <= dev->tnodeWidth)
 		dev->chunkGroupBits = 0;
-	} else {
-		dev->chunkGroupBits = bits - 16;
-	}
+	else
+		dev->chunkGroupBits = bits - dev->tnodeWidth;
+		
 
 	dev->chunkGroupSize = 1 << dev->chunkGroupBits;
 
--- a/yaffs_guts.h
+++ b/yaffs_guts.h
@@ -14,7 +14,7 @@
  *
  * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
  *
- * $Id: yaffs_guts.h,v 1.16 2005-10-09 07:55:00 charles Exp $
+ * $Id: yaffs_guts.h,v 1.17 2005-12-07 21:49:18 charles Exp $
  */
 
 #ifndef __YAFFS_GUTS_H__
@@ -325,7 +325,7 @@ union yaffs_Tnode_union {
 #else
 	union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];
 #endif
-	__u16 level0[YAFFS_NTNODES_LEVEL0];
+/*	__u16 level0[YAFFS_NTNODES_LEVEL0]; */
 
 };
 
@@ -533,6 +533,8 @@ struct yaffs_DeviceStruct {
 	 */
 	void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
 	
+	int wideTnodesDisabled; /* Set to disable wide tnodes */
+	
 
 	/* End of stuff that must be set before initialisation. */
 
@@ -540,6 +542,11 @@ struct yaffs_DeviceStruct {
 
 	__u16 chunkGroupBits;	/* 0 for devices <= 32MB. else log2(nchunks) - 16 */
 	__u16 chunkGroupSize;	/* == 2^^chunkGroupBits */
+	
+	/* Stuff to support wide tnodes */
+	__u32 tnodeWidth;
+	__u32 tnodeMask;
+	
 
 #ifdef __KERNEL__
 
--- a/yaffs_mtdif2.c
+++ b/yaffs_mtdif2.c
@@ -16,7 +16,7 @@
 /* mtd interface for YAFFS2 */
 
 const char *yaffs_mtdif2_c_version =
-    "$Id: yaffs_mtdif2.c,v 1.8 2005-09-20 05:23:41 charles Exp $";
+    "$Id: yaffs_mtdif2.c,v 1.9 2005-12-07 21:49:18 charles Exp $";
 
 #include "yportenv.h"
 
@@ -93,7 +93,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
 	   ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p"
 	    TENDSTR), chunkInNAND, data, tags));
 
-	if (data && tags) {
+	if (1 ||  /* Always do this */
+	    data && tags) {
 		if (dev->useNANDECC) {
 			retval =
 			    mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,