X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=c5be37ff748c02f431dde13b2ad10f7186737cfd;hp=4783f85e92fbed109d200c401714735d83d26f80;hb=69081134a4d0f5059560e10bc49774b1063a6c87;hpb=56f93d87556bc0802ea8d5b080d9e8265bc4e9c1 diff --git a/yaffs_guts.c b/yaffs_guts.c index 4783f85..c5be37f 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.21 2005-10-09 07:55:00 charles Exp $"; + "$Id: yaffs_guts.c,v 1.26 2005-12-19 21:46:07 charles Exp $"; #include "yportenv.h" @@ -538,15 +538,24 @@ 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 *curr; + 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)); + newTnodes = YMALLOC(nTnodes * tnodeSize); + mem = (__u8 *)newTnodes; if (!newTnodes) { T(YAFFS_TRACE_ERROR, @@ -555,6 +564,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 +577,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++) { + curr = (yaffs_Tnode *) &mem[i * tnodeSize]; + next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize]; + curr->internal[0] = next; + } + + curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize]; + curr->internal[0] = dev->freeTnodes; + dev->freeTnodes = (yaffs_Tnode *)mem; + +#endif + + dev->nFreeTnodes += nTnodes; dev->nTnodesCreated += nTnodes; @@ -615,7 +640,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 +691,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 +966,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 +994,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 +1065,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 +2459,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 +2488,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 +2496,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 +2539,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 +2605,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 +2684,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; } @@ -2660,14 +2730,6 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn) if (markNAND && bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) { -#ifdef CONFIG_MTD_NAND_VERIFY_WRITE - - /* Read data before write, to ensure correct ecc - * if we're using MTD verification under Linux - */ - yaffs_ReadChunkFromNAND(dev, chunkId, NULL, &spare, 0); -#endif - yaffs_InitialiseTags(&tags); tags.chunkDeleted = 1; @@ -4832,11 +4894,13 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) break; case YAFFS_OBJECT_TYPE_HARDLINK: - in->variant.hardLinkVariant.equivalentObjectId = + if(!in->deleted) { + in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId; - in->hardLinks.next = + in->hardLinks.next = (struct list_head *) hardList; - hardList = in; + hardList = in; + } break; case YAFFS_OBJECT_TYPE_DIRECTORY: /* Do nothing */ @@ -5333,7 +5397,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) int extraBits; int nBlocks; - T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR))); /* Check stuff that must be set */ @@ -5416,16 +5480,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; @@ -5536,7 +5617,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) yaffs_VerifyFreeChunks(dev); - T(YAFFS_TRACE_ALWAYS, + T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); return YAFFS_OK;