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

📄 yaffs_guts.cpp

📁 文件系统在DSP上的实现
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		// Clean it up...		bi->blockState = YAFFS_BLOCK_STATE_EMPTY;		dev->nErasedBlocks++;		bi->pagesInUse = 0;		bi->softDeletions = 0;		yaffs_ClearChunkBits(dev,blockNo);			T(YAFFS_TRACE_ERASE,(TSTR("Erased block %d" TENDSTR),blockNo));	}	/*else								//BY CEN  不产生坏块	{		yaffs_RetireBlock(dev,blockNo);		T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Block %d retired" TENDSTR),blockNo));	}*/}//描述:返回一个空block(blockState == YAFFS_BLOCK_STATE_EMPTY)的号码,如果没有则返回-1static int yaffs_FindBlockForAllocation(yaffs_Device *dev){	int i;		yaffs_BlockInfo *bi;		if(dev->nErasedBlocks < 1)	{		// Hoosterman we've got a problem.		// Can't get space to gc		T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no space during gc" TENDSTR)));		return -1;	}		// Find an empty block.		for(i = dev->startBlock; i <= dev->endBlock; i++)	{		dev->allocationBlockFinder++;		if(dev->allocationBlockFinder <dev->startBlock || dev->allocationBlockFinder> dev->endBlock) 		{			dev->allocationBlockFinder = dev->startBlock;		}				bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder);		if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY)		{			bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING;			dev->nErasedBlocks--;						return dev->allocationBlockFinder;		}	}		return -1;	}//描述:分配一个chunk,返回chunkInNAMD,全部都是根据内存中的yaffs_BlockInfo查找,并不用搜索FLASHstatic int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve){	int retVal;	yaffs_BlockInfo *bi;		if(dev->allocationBlock < 0)  //原来的block的chunk已经用完	{		// Get next block to allocate off		dev->allocationBlock = yaffs_FindBlockForAllocation(dev); 		           //返回一个空block(blockState == YAFFS_BLOCK_STATE_EMPTY)的号码,如果没有则返回-1		dev->allocationPage = 0;	}		if(!useReserve &&  dev->nErasedBlocks <= dev->nReservedBlocks)  //剩下的擦除块属于保留,	{                                                               //并且规定不得使用保留块  		// Not enough space to allocate unless we're allowed to use the reserve.		return -1;	}		// Next page please....	if(dev->allocationBlock >= 0)	{		bi = yaffs_GetBlockInfo(dev,dev->allocationBlock);				retVal = (dev->allocationBlock * dev->nChunksPerBlock) + 			  	  dev->allocationPage;   //$$$$:返回chunkInNAMD		bi->pagesInUse++;		yaffs_SetChunkBit(dev,dev->allocationBlock,dev->allocationPage);		dev->allocationPage++;				dev->nFreeChunks--;				// If the block is full set the state to full		if(dev->allocationPage >= dev->nChunksPerBlock)		{			bi->blockState = YAFFS_BLOCK_STATE_FULL;			dev->allocationBlock = -1;		}		return retVal;			}	T(YAFFS_TRACE_ERROR,(TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));	return -1;	}// To determine if we have enough space we just look at the // number of erased blocks.// The cache is allowed to use reserved blocks.static int yaffs_CheckSpaceForChunkCache(yaffs_Device *dev){	return (dev->nErasedBlocks >= dev->nReservedBlocks);}//描述:回收一个block内有用的chunk,把它们写到一个新blockstatic int  yaffs_GarbageCollectBlock(yaffs_Device *dev,int block){	int oldChunk;	int newChunk;	int chunkInBlock;	int markNAND;			yaffs_Spare spare;	yaffs_Tags  tags;	__u8  buffer[YAFFS_BYTES_PER_CHUNK];	//	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,block);		yaffs_Object *object;	//T(("Collecting block %d n %d bits %x\n",block, bi->pagesInUse, bi->pageBits));			for(chunkInBlock = 0,oldChunk = block * dev->nChunksPerBlock; 	    chunkInBlock < dev->nChunksPerBlock && yaffs_StillSomeChunkBits(dev,block);	    chunkInBlock++, oldChunk++ )	{		if(yaffs_CheckChunkBit(dev,block,chunkInBlock))  //本次的chunk(chunkInBlock)的bit为1,即数据有效		{						// This page is in use and might need to be copied off						markNAND = 1;						//T(("copying page %x from %d to %d\n",mask,oldChunk,newChunk));						yaffs_ReadChunkFromNAND(dev,oldChunk,buffer, &spare,1);						yaffs_GetTagsFromSpare(dev,&spare,&tags);			object = yaffs_FindObjectByNumber(dev,tags.objectId);						if(object && object->deleted && tags.chunkId != 0)			{				// Data chunk in a deleted file, throw it away				// It's a deleted data chunk,				// No need to copy this, just forget about it and fix up the				// object.								//yaffs_PutChunkIntoFile(object, tags.chunkId, 0,0); 				//文件被删除了,但它的数据chunk还是有效的,ChunkBit还是为1,在删除文件的时候只是使				//object->deleted为1,并没有对数据chunk进行操作,				//在垃圾回收时遇到这样的数据chunk,不用回收,让它在块擦除时被擦掉				object->nDataChunks--;								if(object->nDataChunks <= 0)				{					// Time to delete the file too					yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top);					object->variant.fileVariant.top = NULL;					T(YAFFS_TRACE_TRACING,(TSTR("yaffs: About to finally delete object %d" TENDSTR),object->objectId));					yaffs_DoGenericObjectDeletion(object);					 				}				markNAND = 0;			}			else if( 0 /* Todo object && object->deleted && object->nDataChunks == 0 */)			{				// Deleted object header with no data chunks.				// Can be discarded and the file deleted.				object->chunkId = 0;				yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top);				object->variant.fileVariant.top = NULL;				yaffs_DoGenericObjectDeletion(object);							}			else if(object)			{				// It's either a data chunk in a live file or				// an ObjectHeader, so we're interested in it.				// NB Need to keep the ObjectHeaders of deleted files				// until the whole file has been deleted off				tags.serialNumber++;				yaffs_LoadTagsIntoSpare(&spare, &tags);				dev->nGCCopies++;				newChunk = yaffs_WriteNewChunkToNAND(dev, buffer, &spare,1);			               //在调用yaffs_WriteNewChunkToNAND()的地方都先yaffs_LoadTagsIntoSpare()初始化好spare				if(newChunk < 0)				{					return YAFFS_FAIL;				}							// Ok, now fix up the Tnodes etc.							if(tags.chunkId == 0)				{					// It's a header					object->chunkId = newChunk;					object->serial = tags.serialNumber;				}				else				{					// It's a data chunk					yaffs_PutChunkIntoFile(object, tags.chunkId, newChunk,0);					                    //把新的chunkInNAND(newChunk)填到文件的树结构的叶子				}			}						yaffs_DeleteChunk(dev,oldChunk,markNAND);			            //清空该chunkInNAND(chunkId)的ChunkBit和该block的信息,markNAND为1,则把spare标为删除并写会FLASH		}	}	return YAFFS_OK;}static yaffs_Object *yaffs_FindDeletedUnlinkedFile(yaffs_Device *dev){	// find a file to delete	struct list_head *i;		yaffs_Object *l;	//Scan the unlinked files looking for one to delete	list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children)	{		if(i)		{			l = list_entry(i, yaffs_Object,siblings);			if(l->deleted)			{				return l;						}		}	}		return NULL;}static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev){	// This does background deletion on unlinked files.. only deleted ones.	// If we don't have a file we're working on then find one	if(!dev->unlinkedDeletion && dev->nDeletedFiles > 0)	{		dev->unlinkedDeletion = yaffs_FindDeletedUnlinkedFile(dev);	}		// OK, we're working on a file...	if(dev->unlinkedDeletion)	{		yaffs_Object *obj = dev->unlinkedDeletion;		int delresult;		int limit; // Number of chunks to delete in a file.				   // NB this can be exceeded, but not by much.				   		limit = -1;		delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit);				if(obj->nDataChunks == 0)		{			// Done all the deleting of data chunks.			// Now dump the header and clean up			yaffs_FreeTnode(dev,obj->variant.fileVariant.top);			obj->variant.fileVariant.top = NULL;			yaffs_DoGenericObjectDeletion(obj);			dev->nDeletedFiles--;			dev->nUnlinkedFiles--;			dev->nBackgroundDeletions++;			dev->unlinkedDeletion = NULL;			}	}}#if 0#define YAFFS_GARBAGE_COLLECT_LOW_WATER 2static int yaffs_CheckGarbageCollection(yaffs_Device *dev){	int block;	int aggressive=0;		//yaffs_DoUnlinkedFileDeletion(dev);		if(dev->nErasedBlocks <= (dev->nReservedBlocks + YAFFS_GARBAGE_COLLECT_LOW_WATER))	{		aggressive = 1;	}				if(aggressive)	{		block = yaffs_FindDirtiestBlock(dev,aggressive);				if(block >= 0)		{			dev->garbageCollections++;			return yaffs_GarbageCollectBlock(dev,block);		}			else		{			return YAFFS_FAIL;		}	}	return YAFFS_OK;}#endif// New garbage collector// If we're very low on erased blocks then we do aggressive garbage collection// otherwise we do "passive" garbage collection.// Aggressive gc looks further (whole array) and will accept dirtier blocks.// Passive gc only inspects smaller areas and will only accept cleaner blocks.//// The idea is to help clear out space in a more spread-out manner.// Dunno if it really does anything useful.////描述:找出已经写满并且有用页面最少的块,并回收该block内有用的chunk,把它们写到一个新blockstatic int yaffs_CheckGarbageCollection(yaffs_Device *dev){	int block;	int aggressive=0;		//yaffs_DoUnlinkedFileDeletion(dev);		if(dev->nErasedBlocks <= (dev->nReservedBlocks + 1))  //已擦除干净的块小于保留水准	{		aggressive = 1;	}				block = yaffs_FindDirtiestBlock(dev,aggressive);	          //找出已经写满并且有用页面最少的块,并返回块号	if(block >= 0)	{		dev->garbageCollections++;		if(!aggressive)		{			dev->passiveGarbageCollections++;		}		T(YAFFS_TRACE_GC,(TSTR("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),dev->nErasedBlocks,aggressive));		return yaffs_GarbageCollectBlock(dev,block); //回收一个block内有用的chunk,把它们写到一个新block		                                            	}		return aggressive ? YAFFS_FAIL : YAFFS_OK;}//////////////////////////// TAGS /////////////////////////////////////////描述:计算好tags->ecc,并把tags的相应字段装入到sparestatic void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr){	yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;		yaffs_CalcTagsECC(tagsPtr);		sparePtr->tagByte0 = tu->asBytes[0];	sparePtr->tagByte1 = tu->asBytes[1];	sparePtr->tagByte2 = tu->asBytes[2];	sparePtr->tagByte3 = tu->asBytes[3];	sparePtr->tagByte4 = tu->asBytes[4];	sparePtr->tagByte5 = tu->asBytes[5];	sparePtr->tagByte6 = tu->asBytes[6];	sparePtr->tagByte7 = tu->asBytes[7];}static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr){	yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;	int result;	tu->asBytes[0]= sparePtr->tagByte0;	tu->asBytes[1]= sparePtr->tagByte1;	tu->asBytes[2]= sparePtr->tagByte2;	tu->asBytes[3]= sparePtr->tagByte3;	tu->asBytes[4]= sparePtr->tagByte4;	tu->asBytes[5]= sparePtr->tagByte5;	tu->asBytes[6]= sparePtr->tagByte6;	tu->asBytes[7]= sparePtr->tagByte7;		result =  yaffs_CheckECCOnTags(tagsPtr);   //????:为什么没有错误处理?	if(result> 0)	{		dev->tagsEccFixed++;	}	else if(result <0)	{		dev->tagsEccUnfixed++;	}}static void yaffs_SpareInitialise(yaffs_Spare *spare){	memset(spare,0xFF,sizeof(yaffs_Spare));}static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_Tags *tags, int *chunkDeleted){	if(tags)	{		yaffs_Spare spare;		if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,NULL,&spare,1) == YAFFS_OK)		{			*chunkDeleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;			yaffs_GetTagsFromSpare(dev,&spare,tags);			return YAFFS_OK;		}		else		{			return YAFFS_FAIL;		}	}		return YAFFS_OK;}#if 0static int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *buffer, yaffs_Tags *tags){	// NB There must be tags, data is optional	// If there is data, then an ECC is calculated on it.		yaffs_Spare spare;		if(!tags)	{		return YAFFS_FAIL;	}		yaffs_SpareInitialise(&spare);  //全部设成0xff		if(!dev->useNANDECC && buffer)	{		yaffs_CalcECC(buffer,&spare);	}		yaffs_LoadTagsIntoSpare(&spare,tags);		return yaffs_WriteChunkToNAND(dev,chunkInNAND,buffer,&spare);	}#endif//描述:根据tags生成spare,buffer作为数据,分配chunk,并写到FLASH中去,返回写到的chunkInNAMDstatic int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_Tags *tags, int useReserve){	// NB There must be tags, data is optional	// If there is data, then an ECC is calculated on it.		yaffs_Spare spare;  //内存中的yaffs_Tags与FLASH中的yaffs_Spare相对应		if(!tags)	{		return YAFFS_FAIL;	}		yaffs_SpareInitialise(&spare);   //全部设成0xff		yaffs_CalcECC(buffer, &spare);   //计算出数据(buffer)的ecc,并放入spare的ecc中	/*if(!dev->useNANDECC && buffer)          	{		yaffs_CalcECC(buffer,&spare);	}*/		yaffs_LoadTagsIntoSpare(&spare, tags);   //计算好tags->ecc,并把tags的相应字段装入到spare		return yaffs_WriteNewChunkToNAND(dev,buffer,&spare,useReserve);  	          //在调用yaffs_WriteNewChunkToNAND()的地方都先yaffs_LoadTagsIntoSpare()初始化好spare	 //把buffer和spare写到FLASH,经过以下各个过程:分配一个chunk,(校验是否擦除OK),写,(读出来校验),     //不成功则重写}//描述:如果tags的chunkId和objectId且chunkDeleted为假,则返回真static int yaffs_TagsMatch(const yaffs_Tags *tags, int objectId, int chunkInObject, int chunkDeleted){	return 	(  tags->chunkId == chunkInObject &&			   tags->objectId == objectId &&			   !chunkDeleted) ? 1 : 0;	}//描述:从该文件的树结构中查找该文件(in)的chunkInInode对应的chunkInNAND,从FLASH中一一读取同组所有Chunk,//      找出objectId和chunkInInode符合的Chunk,返回chunkInNAND和从FLASH

⌨️ 快捷键说明

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