📄 yaffs_guts.c
字号:
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 0static 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 0void 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 directlystatic 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 outstatic 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 liststatic 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 0void 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++) { if(yaffs_CheckChunkBit(dev,theChunk / dev->nChunksPerBlock,theChunk % dev->nChunksPerBlock)) { yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL,tags); if(yaffs_TagsMatch(tags,objectId,chunkInInode)) { // found it; return theChunk; } } theChunk++; } return -1;}// DeleteWorker scans backwards through the tnode tree and deletes all the// chunks and tnodes in the file// Returns 1 if the tree was deleted. Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit){ int i; int chunkInInode; int theChunk; yaffs_ExtendedTags tags; int foundChunk; yaffs_Device *dev = in->myDev; int allDone = 1; if(tn) { if(level > 0) { for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--) { if(tn->internal[i]) { if(limit && (*limit) < 0) { allDone = 0; } else { allDone = yaffs_DeleteWorker(in,tn->internal[i],level - 1, (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i ,limit); } if(allDone) { yaffs_FreeTnode(dev,tn->internal[i]); tn->internal[i] = NULL; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -