From f8ce690845de29ca75d312207c8e59eac8bf85d4 Mon Sep 17 00:00:00 2001 From: charles Date: Wed, 7 Dec 2005 21:49:18 +0000 Subject: [PATCH 1/1] Wide tnode support --- direct/dtest.c | 55 +++++++++++++- direct/yaffs_fileem2k.h | 2 +- direct/yaffscfg2k.c | 5 +- yaffs_guts.c | 154 +++++++++++++++++++++++++++++++--------- yaffs_guts.h | 11 ++- yaffs_mtdif2.c | 5 +- 6 files changed, 189 insertions(+), 43 deletions(-) diff --git a/direct/dtest.c b/direct/dtest.c index 3679b25..a48c618 100644 --- a/direct/dtest.c +++ b/direct/dtest.c @@ -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"); diff --git a/direct/yaffs_fileem2k.h b/direct/yaffs_fileem2k.h index 222df53..bf17f2c 100644 --- 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) diff --git a/direct/yaffscfg2k.c b/direct/yaffscfg2k.c index e63411a..38c1f30 100644 --- a/direct/yaffscfg2k.c +++ b/direct/yaffscfg2k.c @@ -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; diff --git a/yaffs_guts.c b/yaffs_guts.c index 1f36cea..b17262b 100644 --- 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_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<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; diff --git a/yaffs_guts.h b/yaffs_guts.h index 73375cc..0a18dee 100644 --- 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__ diff --git a/yaffs_mtdif2.c b/yaffs_mtdif2.c index ee46296..8319481 100644 --- 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(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, -- 2.30.2