⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yaffs_guts.c

📁 yaffs2
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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--;	}	return tn;}static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev){	yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);		if(tn)		memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);	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++;	}}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));  }}__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) {		/* 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 >>			       ( 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) {					chunkInInode =					    (chunkOffset <<					     YAFFS_TNODES_LEVEL0_BITS) + i;					foundChunk =					    yaffs_FindChunkInGroup(dev,								   theChunk,								   &tags,								   in->objectId,								   chunkInInode);					if (foundChunk > 0) {						yaffs_DeleteChunk(dev,								  foundChunk, 1,								  __LINE__);						in->nDataChunks--;						if (limit) {							*limit = *limit - 1;							if (*limit <= 0) {								hitLimit = 1;							}						}					}					yaffs_PutLevel0Tnode(dev,tn,i,0);				}			}			return (i < 0) ? 1 : 0;		}	}	return 1;}static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk){	yaffs_BlockInfo *theBlock;	T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk));	theBlock = yaffs_GetBlockInfo(dev, chunk / dev->nChunksPerBlock);	if (theBlock) {		theBlock->softDeletions++;		dev->nFreeChunks++;	}}/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file. * All soft deleting does is increment the block's softdelete count and pulls the chunk out * of the tnode. * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted. */ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,				  __u32 level, int chunkOffset){	int i;	int theChunk;	int allDone = 1;	yaffs_Device *dev = in->myDev;	if (tn) {		if (level > 0) {			for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;			     i--) {				if (tn->internal[i]) {					allDone =					    yaffs_SoftDeleteWorker(in,								   tn->								   internal[i],								   level - 1,								   (chunkOffset								    <<								    YAFFS_TNODES_INTERNAL_BITS)								   + i);					if (allDone) {						yaffs_FreeTnode(dev,								tn->								internal[i]);						tn->internal[i] = NULL;					} else {						/* Hoosterman... how could this happen? */					}				}			}			return (allDone) ? 1 : 0;		} else if (level == 0) {			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; 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.					 */					yaffs_SoftDeleteChunk(dev, theChunk);					yaffs_PutLevel0Tnode(dev,tn,i,0);				}			}			return 1;		}	}	return 1;}static void yaffs_SoftDeleteFile(yaffs_Object * obj){	if (obj->deleted &&	    obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) {		if (obj->nDataChunks <= 0) {			/* Empty file with no duplicate object headers, just delete it immediately */			yaffs_FreeTnode(obj->myDev,					obj->variant.fileVariant.top);			obj->variant.fileVariant.top = NULL;			T(YAFFS_TRACE_TRACING,			  (TSTR("yaffs: Deleting empty file %d" TENDSTR),			   obj->objectId));			yaffs_DoGenericObjectDeletion(obj);		} else {			yaffs_SoftDeleteWorker(obj,					       obj->variant.fileVariant.top,					       obj->variant.fileVariant.					       topLevel, 0);			obj->softDeleted = 1;		}	}}/* Pruning removes any part of the file structure tree that is beyond the * bounds of the file (ie that does not point to chunks). * * A file should only get pruned when its size is reduced. * * Before pruning, the chunks must be pulled from the tree and the * level 0 tnode entries must be zeroed out. * Could also use this for file deletion, but that's probably better handled * by a special case. */static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn,				      __u32 level, int del0){	int i;	int hasData;	if (tn) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -