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

📄 yaffs_guts.c

📁 USBONs3c2410.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
//// Mknod (create) a new object.// equivalentObject only has meaning for a hard link;// aliasString only has meaning for a sumlink.// rdev only has meaning for devices (a subset of special objects)yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,								 yaffs_Object *parent,								 const char *name, 								 __u32 mode,								 __u32 uid,								 __u32 gid,								 yaffs_Object *equivalentObject,								 const char *aliasString,								 __u32 rdev){	yaffs_Object *in;	yaffs_Device *dev = parent->myDev;		// Check if the entry exists. If it does then fail the call since we don't want a dup.	if(yaffs_FindObjectByName(parent,name))	{		return NULL;	}		in = yaffs_CreateNewObject(dev,-1,type);		if(in)	{		in->chunkId = -1;		in->valid = 1;		in->variantType = type;		in->st_mode  = mode;		#ifdef CONFIG_YAFFS_WINCE		yfsd_WinFileTimeNow(in->win_atime);		in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];		in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];		#else		in->st_atime = in->st_mtime = in->st_ctime = Y_CURRENT_TIME;		in->st_rdev  = rdev;		in->st_uid   = uid;		in->st_gid   = gid;#endif				in->nDataChunks = 0;		yaffs_SetObjectName(in,name);		in->dirty = 1;				yaffs_AddObjectToDirectory(parent,in);				in->myDev = parent->myDev;								switch(type)		{			case YAFFS_OBJECT_TYPE_SYMLINK:				in->variant.symLinkVariant.alias = yaffs_CloneString(aliasString);				break;			case YAFFS_OBJECT_TYPE_HARDLINK:				in->variant.hardLinkVariant.equivalentObject = equivalentObject;				in->variant.hardLinkVariant.equivalentObjectId = equivalentObject->objectId;				list_add(&in->hardLinks,&equivalentObject->hardLinks);				break;			case YAFFS_OBJECT_TYPE_FILE: // do nothing			case YAFFS_OBJECT_TYPE_DIRECTORY: // do nothing			case YAFFS_OBJECT_TYPE_SPECIAL: // do nothing			case YAFFS_OBJECT_TYPE_UNKNOWN:				break;		}		if(/*yaffs_GetNumberOfFreeChunks(dev) <= 0 || */		   yaffs_UpdateObjectHeader(in,name,0) < 0)		{			// Could not create the object header, fail the creation			yaffs_AbortHalfCreatedObject(in);			in = NULL;		}	}		return in;}yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE,parent,name,mode,uid,gid,NULL,NULL,0);}yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,0);}yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid, __u32 rdev){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,rdev);}yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,const char *alias){	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK,parent,name,mode,uid,gid,NULL,alias,0);}// NB yaffs_Link returns the object id of the equivalent object.yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject){	// Get the real object in case we were fed a hard link as an equivalent object	equivalentObject = yaffs_GetEquivalentObject(equivalentObject);		if(yaffs_MknodObject(YAFFS_OBJECT_TYPE_HARDLINK,parent,name,0,0,0,equivalentObject,NULL,0))	{		return equivalentObject;	}	else	{		return NULL;	}	}static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const char *newName,int force){	int unlinkOp;	if(newDir == NULL)	{		newDir = obj->parent; // use the old directory	}	unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE);		// If the object is a file going into the unlinked directory, then it is OK to just stuff it in since	// duplicate names are allowed.	// Otherwise only proceed if the new name does not exist and if we're putting it into a directory.	if( (unlinkOp|| 		 force || 		 !yaffs_FindObjectByName(newDir,newName))  &&	     newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)	{		yaffs_SetObjectName(obj,newName);		obj->dirty = 1;				yaffs_AddObjectToDirectory(newDir,obj);				if(unlinkOp) obj->unlinked = 1;						if(yaffs_UpdateObjectHeader(obj,newName,0) >= 0)		{			return YAFFS_OK;		}	}		return YAFFS_FAIL;}int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName){	yaffs_Object *obj;	int force = 0;	#ifdef CONFIG_YAFFS_CASE_INSENSITIVE	// Special case for WinCE.	// While look-up is case insensitive, the name isn't.	// THerefore we might want to change x.txt to X.txt	if(oldDir == newDir && _stricmp(oldName,newName) == 0)	{		force = 1;	}	#endif		obj = yaffs_FindObjectByName(oldDir,oldName);	if(obj && obj->renameAllowed)	{		return yaffs_ChangeObjectName(obj,newDir,newName,force);	}	return YAFFS_FAIL;}static int yaffs_CheckObjectHashSanity(yaffs_Device *dev){	// Scan the buckets and check that the lists 	// have as many members as the count says there are	int bucket;	int countEm;	struct list_head *j;	int ok = YAFFS_OK;		for(bucket = 0; bucket < YAFFS_NOBJECT_BUCKETS; bucket++)	{		countEm = 0;				list_for_each(j,&dev->objectBucket[bucket].list)		{			countEm++;		}				if(countEm != dev->objectBucket[bucket].count)		{			T(YAFFS_TRACE_ERROR,(TSTR("Inode hash inconsistency" TENDSTR)));			ok = YAFFS_FAIL;		}	}	return ok;}#if 0void yaffs_ObjectTest(yaffs_Device *dev){	yaffs_Object *in[1000];	int inNo[1000];	yaffs_Object *inold[1000];	int i;	int j;		memset(in,0,1000*sizeof(yaffs_Object *));	memset(inold,0,1000*sizeof(yaffs_Object *));		yaffs_CheckObjectHashSanity(dev);		for(j = 0; j < 10; j++)	{		//T(("%d\n",j));				for(i = 0; i < 1000; i++)		{			in[i] = yaffs_CreateNewObject(dev,-1,YAFFS_OBJECT_TYPE_FILE);			if(!in[i])			{				YINFO("No more inodes");			}			else			{				inNo[i] = in[i]->objectId;			}		}				for(i = 0; i < 1000; i++)		{			if(yaffs_FindObjectByNumber(dev,inNo[i]) != in[i])			{				//T(("Differnce in look up test\n"));			}			else			{				// T(("Look up ok\n"));			}		}				yaffs_CheckObjectHashSanity(dev);			for(i = 0; i < 1000; i+=3)		{			yaffs_FreeObject(in[i]);				in[i] = NULL;		}					yaffs_CheckObjectHashSanity(dev);	}		}#endif/////////////////////////// Block Management and Page Allocation ///////////////////static int yaffs_InitialiseBlocks(yaffs_Device *dev,int nBlocks){	dev->allocationBlock = -1; // force it to get a new one	//Todo we're assuming the malloc will pass.	dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo));	// Set up dynamic blockinfo stuff.	dev->chunkBitmapStride = (dev->nChunksPerBlock+7)/8;	dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);	if(dev->blockInfo && dev->chunkBits)	{		memset(dev->blockInfo,0,nBlocks * sizeof(yaffs_BlockInfo));		memset(dev->chunkBits,0,dev->chunkBitmapStride * nBlocks);		return YAFFS_OK;	}		return YAFFS_FAIL;	}static void yaffs_DeinitialiseBlocks(yaffs_Device *dev){	YFREE(dev->blockInfo);	dev->blockInfo = NULL;	YFREE(dev->chunkBits);	dev->chunkBits = NULL;}// FindDiretiestBlock is used to select the dirtiest block (or close enough)// for garbage collection.static int yaffs_FindDirtiestBlock(yaffs_Device *dev,int aggressive){	int b = dev->currentDirtyChecker;		int i;	int iterations;	int dirtiest = -1;	int pagesInUse; 	yaffs_BlockInfo *bi;	// If we're doing aggressive GC then we are happy to take a less-dirty block, and	// search further.		pagesInUse = (aggressive)? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;	if(aggressive)	{		iterations = dev->endBlock - dev->startBlock + 1;	}	else	{		iterations = dev->endBlock - dev->startBlock + 1;		iterations = iterations / 16;		if(iterations > 200)		{			iterations = 200;		}	}		for(i = 0; i <= iterations && pagesInUse > 0 ; i++)	{		b++;		if ( b < dev->startBlock || b > dev->endBlock)		{			b =  dev->startBlock;		}		if(b < dev->startBlock || b > dev->endBlock)		{			T(YAFFS_TRACE_ERROR,(TSTR("**>> Block %d is not valid" TENDSTR),b));			YBUG();		}				bi = yaffs_GetBlockInfo(dev,b);				if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&		   (bi->pagesInUse - bi->softDeletions )< pagesInUse)		{			dirtiest = b;			pagesInUse = (bi->pagesInUse - bi->softDeletions);		}	}		dev->currentDirtyChecker = b;		return dirtiest;}static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo){	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,blockNo);		int erasedOk = 0;		// If the block is still healthy erase it and mark as clean.	// If the block has had a data failure, then retire it.	bi->blockState = YAFFS_BLOCK_STATE_DIRTY;	if(!bi->needsRetiring)	{		erasedOk = yaffs_EraseBlockInNAND(dev,blockNo);		if(!erasedOk)		{			T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Erasure failed %d" TENDSTR),blockNo));		}	}		if( erasedOk )	{		// 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	{		yaffs_RetireBlock(dev,blockNo);		T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Block %d retired" TENDSTR),blockNo));	}}static 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;	}static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve){	int retVal;	yaffs_BlockInfo *bi;		if(dev->allocationBlock < 0)	{		// Get next block to allocate off		dev->allocationBlock = yaffs_FindBlockForAllocation(dev);		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;		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);}static 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))		{						// 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); 				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

⌨️ 快捷键说明

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