📄 yaffs_guts.c
字号:
{
yaffs_HandleWriteChunkError(dev,chunk);
}
}
} while(chunk >= 0 && ! writeOk);
if(attempts > 1)
{
T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write required %d attempts" TENDSTR),attempts));
dev->nRetriedWrites+= (attempts - 1);
}
return chunk;
}
#endif
///
// Functions for robustisizing
//
//
static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND)
{
yaffs_MarkBlockBad(dev,blockInNAND);
yaffs_GetBlockInfo(dev,blockInNAND)->blockState = YAFFS_BLOCK_STATE_DEAD;
dev->nRetiredBlocks++;
}
static int yaffs_RewriteBufferedBlock(yaffs_Device *dev)
{
dev->doingBufferedBlockRewrite = 1;
//
// Remove erased chunks
// Rewrite existing chunks to a new block
// Set current write block to the new block
dev->doingBufferedBlockRewrite = 0;
return 1;
}
static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND)
{
int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
// Mark the block for retirement
yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>>Block %d marked for retirement" TENDSTR),blockInNAND));
//TODO
// Just do a garbage collection on the affected block then retire the block
// NB recursion
}
static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND)
{
}
static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
{
}
static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_ExtendedTags *tags)
{
}
static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND)
{
int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
// Mark the block for retirement
yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
// Delete the chunk
yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__);
}
#if 0
static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1,int dataSize)
{
if( memcmp(d0,d1,dataSize) != 0 ||
s0->tagByte0 != s1->tagByte0 ||
s0->tagByte1 != s1->tagByte1 ||
s0->tagByte2 != s1->tagByte2 ||
s0->tagByte3 != s1->tagByte3 ||
s0->tagByte4 != s1->tagByte4 ||
s0->tagByte5 != s1->tagByte5 ||
s0->tagByte6 != s1->tagByte6 ||
s0->tagByte7 != s1->tagByte7 ||
s0->ecc1[0] != s1->ecc1[0] ||
s0->ecc1[1] != s1->ecc1[1] ||
s0->ecc1[2] != s1->ecc1[2] ||
s0->ecc2[0] != s1->ecc2[0] ||
s0->ecc2[1] != s1->ecc2[1] ||
s0->ecc2[2] != s1->ecc2[2] )
{
return 0;
}
return 1;
}
#endif
///////////////////////// Object management //////////////////
// List of spare objects
// The list is hooked together using the first pointer
// in the object
// static yaffs_Object *yaffs_freeObjects = NULL;
// static int yaffs_nFreeObjects;
// static yaffs_ObjectList *yaffs_allocatedObjectList = NULL;
// static yaffs_ObjectBucket yaffs_objectBucket[YAFFS_NOBJECT_BUCKETS];
static __u16 yaffs_CalcNameSum(const YCHAR *name)
{
__u16 sum = 0;
__u16 i = 1;
YUCHAR *bname = (YUCHAR *)name;
if(bname)
{
while ((*bname) && (i <=YAFFS_MAX_NAME_LENGTH))
{
#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
sum += yaffs_toupper(*bname) * i;
#else
sum += (*bname) * i;
#endif
i++;
bname++;
}
}
return sum;
}
void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name)
{
#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
if(name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH)
{
yaffs_strcpy(obj->shortName,name);
}
else
{
obj->shortName[0]=_Y('\0');
}
#endif
obj->sum = yaffs_CalcNameSum(name);
}
#if 0
void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
{
yaffs_ECCCalculate(data , spare->ecc1);
yaffs_ECCCalculate(&data[256] , spare->ecc2);
}
#endif
///////////////////////// TNODES ///////////////////////
// List of spare tnodes
// The list is hooked together using the first pointer
// in the tnode.
//static yaffs_Tnode *yaffs_freeTnodes = NULL;
// static int yaffs_nFreeTnodes;
//static yaffs_TnodeList *yaffs_allocatedTnodeList = NULL;
// yaffs_CreateTnodes creates a bunch more tnodes and
// adds them to the tnode free list.
// Don't use this function directly
static int yaffs_CreateTnodes(yaffs_Device *dev,int nTnodes)
{
int i;
yaffs_Tnode *newTnodes;
yaffs_TnodeList *tnl;
if(nTnodes < 1) return YAFFS_OK;
// make these things
newTnodes = YMALLOC(nTnodes * sizeof(yaffs_Tnode));
if (!newTnodes)
{
T(YAFFS_TRACE_ERROR,(TSTR("yaffs: Could not allocate Tnodes"TENDSTR)));
return YAFFS_FAIL;
}
// Hook them into the free list
for(i = 0; i < nTnodes - 1; i++)
{
newTnodes[i].internal[0] = &newTnodes[i+1];
#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = 1;
#endif
}
newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = 1;
#endif
dev->freeTnodes = newTnodes;
dev->nFreeTnodes+= nTnodes;
dev->nTnodesCreated += nTnodes;
// Now add this bunch of tnodes to a list for freeing up.
// NB If we can't add this to the management list it isn't fatal
// but it just means we can't free this bunch of tnodes later.
tnl = YMALLOC(sizeof(yaffs_TnodeList));
if(!tnl)
{
T(YAFFS_TRACE_ERROR,(TSTR("yaffs: Could not add tnodes to management list" TENDSTR)));
}
else
{
tnl->tnodes = newTnodes;
tnl->next = dev->allocatedTnodeList;
dev->allocatedTnodeList = tnl;
}
T(YAFFS_TRACE_ALLOCATE,(TSTR("yaffs: Tnodes added" TENDSTR)));
return YAFFS_OK;
}
// GetTnode gets us a clean tnode. Tries to make allocate more if we run out
static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
{
yaffs_Tnode *tn = NULL;
// If there are none left make more
if(!dev->freeTnodes)
{
yaffs_CreateTnodes(dev,YAFFS_ALLOCATION_NTNODES);
}
if(dev->freeTnodes)
{
tn = dev->freeTnodes;
#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
if(tn->internal[YAFFS_NTNODES_INTERNAL] != 1)
{
// Hoosterman, this thing looks like it isn't in the list
T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 1" TENDSTR)));
}
#endif
dev->freeTnodes = dev->freeTnodes->internal[0];
dev->nFreeTnodes--;
// zero out
memset(tn,0,sizeof(yaffs_Tnode));
}
return tn;
}
// FreeTnode frees up a tnode and puts it back on the free list
static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn)
{
if(tn)
{
#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
if(tn->internal[YAFFS_NTNODES_INTERNAL] != 0)
{
// Hoosterman, this thing looks like it is already in the list
T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 2" TENDSTR)));
}
tn->internal[YAFFS_NTNODES_INTERNAL] = 1;
#endif
tn->internal[0] = dev->freeTnodes;
dev->freeTnodes = tn;
dev->nFreeTnodes++;
}
}
static void yaffs_DeinitialiseTnodes(yaffs_Device*dev)
{
// Free the list of allocated tnodes
yaffs_TnodeList *tmp;
while(dev->allocatedTnodeList)
{
tmp = dev->allocatedTnodeList->next;
YFREE(dev->allocatedTnodeList->tnodes);
YFREE(dev->allocatedTnodeList);
dev->allocatedTnodeList = tmp;
}
dev->freeTnodes = NULL;
dev->nFreeTnodes = 0;
}
static void yaffs_InitialiseTnodes(yaffs_Device*dev)
{
dev->allocatedTnodeList = NULL;
dev->freeTnodes = NULL;
dev->nFreeTnodes = 0;
dev->nTnodesCreated = 0;
}
#if 0
void yaffs_TnodeTest(yaffs_Device *dev)
{
int i;
int j;
yaffs_Tnode *tn[1000];
YINFO("Testing TNodes");
for(j = 0; j < 50; j++)
{
for(i = 0; i < 1000; i++)
{
tn[i] = yaffs_GetTnode(dev);
if(!tn[i])
{
YALERT("Getting tnode failed");
}
}
for(i = 0; i < 1000; i+=3)
{
yaffs_FreeTnode(dev,tn[i]);
tn[i] = NULL;
}
}
}
#endif
////////////////// END OF TNODE MANIPULATION ///////////////////////////
/////////////// Functions to manipulate the look-up tree (made up of tnodes)
// The look up tree is represented by the top tnode and the number of topLevel
// in the tree. 0 means only the level 0 tnode is in the tree.
// FindLevel0Tnode finds the level 0 tnode, if one exists.
// Used when reading.....
static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev,yaffs_FileStructure *fStruct, __u32 chunkId)
{
yaffs_Tnode *tn = fStruct->top;
__u32 i;
int requiredTallness;
int level = fStruct->topLevel;
// Check sane level and chunk Id
if(level < 0 || level > YAFFS_TNODES_MAX_LEVEL)
{
// char str[50];
// sprintf(str,"Bad level %d",level);
// YALERT(str);
return NULL;
}
if(chunkId > YAFFS_MAX_CHUNK_ID)
{
// char str[50];
// sprintf(str,"Bad chunkId %d",chunkId);
// YALERT(str);
return NULL;
}
// First check we're tall enough (ie enough topLevel)
i = chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS);
requiredTallness = 0;
while(i)
{
i >>= YAFFS_TNODES_INTERNAL_BITS;
requiredTallness++;
}
if(requiredTallness > fStruct->topLevel)
{
// Not tall enough, so we can't find it, return NULL.
return NULL;
}
// Traverse down to level 0
while (level > 0 && tn)
{
tn = tn->internal[(chunkId >>(/* dev->chunkGroupBits + */ YAFFS_TNODES_LEVEL0_BITS + (level-1) * YAFFS_TNODES_INTERNAL_BITS)) &
YAFFS_TNODES_INTERNAL_MASK];
level--;
}
return tn;
}
// AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree.
// This happens in two steps:
// 1. If the tree isn't tall enough, then make it taller.
// 2. Scan down the tree towards the level 0 tnode adding tnodes if required.
//
// Used when modifying the tree.
//
static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId)
{
yaffs_Tnode *tn;
int requiredTallness;
int i;
int l;
__u32 x;
//T((TSTR("AddOrFind topLevel=%d, chunk=%d"),fStruct->topLevel,chunkId));
// Check sane level and page Id
if(fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL)
{
// char str[50];
// sprintf(str,"Bad level %d",fStruct->topLevel);
// YALERT(str);
return NULL;
}
if(chunkId > YAFFS_MAX_CHUNK_ID)
{
// char str[50];
// sprintf(str,"Bad chunkId %d",chunkId);
// YALERT(str);
return NULL;
}
// First check we're tall enough (ie enough topLevel)
x = chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS);
requiredTallness = 0;
while(x)
{
x >>= YAFFS_TNODES_INTERNAL_BITS;
requiredTallness++;
}
//T((TSTR(" required=%d"),requiredTallness));
if(requiredTallness > fStruct->topLevel)
{
// Not tall enough,gotta make the tree taller
for(i = fStruct->topLevel; i < requiredTallness; i++)
{
//T((TSTR(" add new top")));
tn = yaffs_GetTnode(dev);
if(tn)
{
tn->internal[0] = fStruct->top;
fStruct->top = tn;
}
else
{
T(YAFFS_TRACE_ERROR,(TSTR("yaffs: no more tnodes" TENDSTR)));
}
}
fStruct->topLevel = requiredTallness;
}
// Traverse down to level 0, adding anything we need
l = fStruct->topLevel;
tn = fStruct->top;
while (l > 0 && tn)
{
x = (chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS + (l-1) * YAFFS_TNODES_INTERNAL_BITS)) &
YAFFS_TNODES_INTERNAL_MASK;
//T((TSTR(" [%d:%d]"),l,i));
if(!tn->internal[x])
{
//T((TSTR(" added")));
tn->internal[x] = yaffs_GetTnode(dev);
}
tn = tn->internal[x];
l--;
}
//TSTR(TENDSTR)));
return tn;
}
int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, yaffs_ExtendedTags *tags, int objectId, int chunkInInode)
{
int j;
for(j = 0; theChunk && j < dev->chunkGroupSize; j++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -