📄 yaffs_guts.c
字号:
if (bi->chunkErrorStrikes > 3) { bi->needsRetiring = 1; /* Too many stikes, so retire this */ T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR))); } }}static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, int erasedOk){ int blockInNAND = chunkInNAND / dev->nChunksPerBlock; yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); yaffs_HandleChunkError(dev, bi); if (erasedOk) { /* Was an actual write failure, so mark the block for retirement */ bi->needsRetiring = 1; T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND)); } /* Delete the chunk */ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);}/*---------------- Name handling functions ------------*/static __u16 yaffs_CalcNameSum(const YCHAR *name){ __u16 sum = 0; __u16 i = 1; const YUCHAR *bname = (const YUCHAR *) name; if (bname) { while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {#ifdef CONFIG_YAFFS_CASE_INSENSITIVE sum += yaffs_toupper(*bname) * i;#else sum += (*bname) * i;#endif i++; bname++; } } return sum;}static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name){#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM memset(obj->shortName, 0, sizeof(YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); 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);}/*-------------------- TNODES ------------------- * List of spare tnodes * The list is hooked together using the first pointer * in the tnode. *//* 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; 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; if (tnodeSize < sizeof(yaffs_Tnode)) tnodeSize = sizeof(yaffs_Tnode); /* make these things */ newTnodes = YMALLOC(nTnodes * tnodeSize); mem = (__u8 *)newTnodes; if (!newTnodes) { T(YAFFS_TRACE_ERROR, (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); return YAFFS_FAIL; } /* 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[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;#endif } newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;#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; /* 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))); return YAFFS_FAIL; } 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_GetTnodeRaw(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] != (void *)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--; } dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ return tn;}static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev){ yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev); int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; if (tnodeSize < sizeof(yaffs_Tnode)) tnodeSize = sizeof(yaffs_Tnode); if (tn) memset(tn, 0, tnodeSize); 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] = (void *)1;#endif tn->internal[0] = dev->freeTnodes; dev->freeTnodes = tn; dev->nFreeTnodes++; } dev->nCheckpointBlocksRequired = 0; /* force recalculation*/}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;}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)); }}static __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) ------ * 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. */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) return NULL; if (chunkId > YAFFS_MAX_CHUNK_ID) return NULL; /* First check we're tall enough (ie enough topLevel) */ i = chunkId >> YAFFS_TNODES_LEVEL0_BITS; requiredTallness = 0; while (i) { i >>= YAFFS_TNODES_INTERNAL_BITS; requiredTallness++; } if (requiredTallness > fStruct->topLevel) return NULL; /* Not tall enough, so we can't find it */ /* Traverse down to level 0 */ while (level > 0 && tn) { tn = tn->internal[(chunkId >> (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. * * If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will * be plugged into the ttree. */static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId, yaffs_Tnode *passedTn){ int requiredTallness; int i; int l; yaffs_Tnode *tn; __u32 x; /* Check sane level and page Id */ if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) return NULL; if (chunkId > YAFFS_MAX_CHUNK_ID) return NULL; /* First check we're tall enough (ie enough topLevel) */ x = chunkId >> YAFFS_TNODES_LEVEL0_BITS; requiredTallness = 0; while (x) { x >>= YAFFS_TNODES_INTERNAL_BITS; requiredTallness++; } if (requiredTallness > fStruct->topLevel) { /* Not tall enough, gotta make the tree taller */ for (i = fStruct->topLevel; i < requiredTallness; i++) { 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; if (l > 0) { while (l > 0 && tn) { x = (chunkId >> (YAFFS_TNODES_LEVEL0_BITS + (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) & YAFFS_TNODES_INTERNAL_MASK; if ((l > 1) && !tn->internal[x]) { /* Add missing non-level-zero tnode */ tn->internal[x] = yaffs_GetTnode(dev); } else if (l == 1) { /* Looking from level 1 at level 0 */ if (passedTn) { /* If we already have one, then release it.*/ if (tn->internal[x]) yaffs_FreeTnode(dev, tn->internal[x]); tn->internal[x] = passedTn; } else if (!tn->internal[x]) { /* Don't have one, none passed in */ tn->internal[x] = yaffs_GetTnode(dev); } } tn = tn->internal[x]; l--; } } else { /* top is level 0 */ if (passedTn) { memcpy(tn, passedTn, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); yaffs_FreeTnode(dev, passedTn); } } return tn;}static 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; } } } return (allDone) ? 1 : 0; } else if (level == 0) { int hitLimit = 0; for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit; i--) { theChunk = yaffs_GetChunkGroupBase(dev, tn, i); if (theChunk) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -