*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.22 2005-10-13 02:17:00 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.25 2005-12-08 00:51:15 charles Exp $";
#include "yportenv.h"
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,
}
/* 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
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;
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;
}
+
+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) ------
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,
}
- tn->level0[i] = 0;
+ yaffs_PutLevel0Tnode(dev,tn,i,0);
}
}
} 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);
}
}
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,
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,
/* 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)); */
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,
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
in->nDataChunks++;
}
- tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] =
- (chunkInNAND >> dev->chunkGroupBits);
+ yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND);
return YAFFS_OK;
}
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 */
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;
yaffs_VerifyFreeChunks(dev);
- T(YAFFS_TRACE_ALWAYS,
+ T(YAFFS_TRACE_TRACING,
(TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
return YAFFS_OK;