Wide tnode support
authorcharles <charles>
Wed, 7 Dec 2005 21:49:18 +0000 (21:49 +0000)
committercharles <charles>
Wed, 7 Dec 2005 21:49:18 +0000 (21:49 +0000)
direct/dtest.c
direct/yaffs_fileem2k.h
direct/yaffscfg2k.c
yaffs_guts.c
yaffs_guts.h
yaffs_mtdif2.c

index 3679b25..a48c618 100644 (file)
@@ -1388,6 +1388,56 @@ void freespace_test(const char *mountpt)
        printf("%d\n%d\n%d\n%d\n",f0, f1,f2,f3);
        
        
+}
+
+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");
+       
+       
+       
 }
 
 
@@ -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");
        
        
        
index 222df53..bf17f2c 100644 (file)
@@ -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)
index e63411a..38c1f30 100644 (file)
@@ -68,9 +68,9 @@ static yaffsfs_DeviceConfiguration yaffsfs_config[] = {
 #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;
index 1f36cea..b17262b 100644 (file)
@@ -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_Object * obj, const YCHAR * name)
 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_Device * dev, int nTnodes)
        }
 
        /* 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_Device * dev, int nTnodes)
        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_Device * dev)
                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_Device * dev)
 
 }
 
+
+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_Object * in, yaffs_Tnode * tn, __u32 level,
 
                        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_Object * in, yaffs_Tnode * tn, __u32 level,
 
                                        }
 
-                                       tn->level0[i] = 0;
+                                       yaffs_PutLevel0Tnode(dev,tn,i,0);
                                }
 
                        }
@@ -985,17 +1064,14 @@ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
                } 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_Object * in, int chunkInInode,
        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_FindAndDeleteChunkInFile(yaffs_Object * in, int 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,
@@ -2423,7 +2495,7 @@ static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode,
 
                /* 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_Object * in)
 
                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_Object * in, int chunkInInode,
                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_Object * in, int chunkInInode,
                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 * dev)
 
        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;
 
index 73375cc..0a18dee 100644 (file)
@@ -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__
 
index ee46296..8319481 100644 (file)
@@ -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(yaffs_Device * dev, int chunkInNAND,
           ("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,