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

📄 yaffs_guts.c

📁 full package of jaffs file system
💻 C
📖 第 1 页 / 共 5 页
字号:
	}		return NULL;}yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type){			yaffs_Object *theObject;	if(number < 0)	{		number = yaffs_CreateNewObjectNumber(dev);	}		theObject = yaffs_AllocateEmptyObject(dev);		if(theObject)	{		theObject->fake = 0;		theObject->renameAllowed = 1;		theObject->unlinkAllowed = 1;		theObject->objectId = number;		yaffs_HashObject(theObject);		theObject->variantType = type;#ifdef CONFIG_YAFFS_WINCE		yfsd_WinFileTimeNow(theObject->win_atime);		theObject->win_ctime[0] = theObject->win_mtime[0] = theObject->win_atime[0];		theObject->win_ctime[1] = theObject->win_mtime[1] = theObject->win_atime[1];#else		theObject->st_atime = theObject->st_mtime = theObject->st_ctime = Y_CURRENT_TIME;		#endif		switch(type)		{			case YAFFS_OBJECT_TYPE_FILE: 				theObject->variant.fileVariant.fileSize = 0;				theObject->variant.fileVariant.scannedFileSize = 0;				theObject->variant.fileVariant.topLevel = 0;				theObject->variant.fileVariant.top  = yaffs_GetTnode(dev);				break;			case YAFFS_OBJECT_TYPE_DIRECTORY:				INIT_LIST_HEAD(&theObject->variant.directoryVariant.children);				break;			case YAFFS_OBJECT_TYPE_SYMLINK:				// No action required				break;			case YAFFS_OBJECT_TYPE_HARDLINK:				// No action required				break;			case YAFFS_OBJECT_TYPE_SPECIAL:				// No action required				break;			case YAFFS_OBJECT_TYPE_UNKNOWN:				// todo this should not happen				break;		}	}		return theObject;}yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaffs_ObjectType type){	yaffs_Object *theObject = NULL;		if(number > 0)	{		theObject = yaffs_FindObjectByNumber(dev,number);	}		if(!theObject)	{		theObject = yaffs_CreateNewObject(dev,number,type);	}		return theObject;}YCHAR *yaffs_CloneString(const YCHAR *str){	YCHAR *newStr = NULL;		if(str && *str)	{		newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR));		yaffs_strcpy(newStr,str);	}	return newStr;	}//// 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 YCHAR *name, 								 __u32 mode,								 __u32 uid,								 __u32 gid,								 yaffs_Object *equivalentObject,								 const YCHAR *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) < 0)		{			// Could not create the object header, fail the creation			yaffs_DestroyObject(in);			in = NULL;		}	}		return in;}yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const YCHAR *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 YCHAR *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 YCHAR *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 YCHAR *name, __u32 mode, __u32 uid, __u32 gid,const YCHAR *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 YCHAR *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 YCHAR *newName,int force){	int unlinkOp;	int deleteOp;	if(newDir == NULL)	{		newDir = obj->parent; // use the old directory	}	// TODO: Do we need this different handling for YAFFS2 and YAFFS1??	if(obj->myDev->isYaffs2)	{		unlinkOp = (newDir == obj->myDev->unlinkedDir);	}	else	{		unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE);	}	deleteOp = (newDir == obj->myDev->deletedDir);		// 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|| 		 deleteOp ||		 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 it is a dletion then we mark it as a shrink for gc purposes.		if(yaffs_UpdateObjectHeader(obj,newName,0,deleteOp) >= 0)		{			return YAFFS_OK;		}	}		return YAFFS_FAIL;}int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object *newDir, const YCHAR *newName){	yaffs_Object *obj;	int force = 0;	#ifdef CONFIG_YAFFS_CASE_INSENSITIVE	// Special case for case insemsitive systems (eg. 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 && yaffs_strcmp(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;}static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, yaffs_BlockInfo *bi){	int i;	__u32 seq;	yaffs_BlockInfo *b;		if(!dev->isYaffs2) return 1; // disqualification only applies to yaffs2.		if(!bi->hasShrinkHeader) return 1; // can gc	// Find the oldest dirty sequence number if we don't know it and save it	// so we don't have to keep recomputing it.	if(!dev->oldestDirtySequence)	{		seq = dev->sequenceNumber;		for(i = dev->startBlock; i <= dev->endBlock; i++)		{			b = yaffs_GetBlockInfo(dev,i);			if(b->blockState == YAFFS_BLOCK_STATE_FULL &&			(b->pagesInUse - b->softDeletions )< dev->nChunksPerBlock &&			b->sequenceNumber < seq)			{		  		seq = b->sequenceNumber;			}		}		dev->oldestDirtySequence = seq;	}	// Can't do gc of this block if there are any blocks older than this one that have	// discarded pages.	return (bi->sequenceNumber <= dev->oldestDirtySequence);			return 1;}// FindDiretiestBlock is used to select the dirtiest block (or close enough)// for garbage collection.//static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,int aggressive){	int b = dev->currentDirtyChecker;		int i;	int iterations;	int dirtiest = -1;	int pagesInUse; 	yaffs_BlockInfo *bi;	static int  nonAggressiveSkip = 0;	// If we're doing aggressive GC then we are happy to take a less-dirty block, and	// search harder.	// else (we're doing a leasurely gc), then we only bother to do this if the	// block has only a few pages in use.		nonAggressiveSkip--;	if(!aggressive &&(nonAggressiveSkip > 0))	{		return -1;	}	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 &&		   yaffs_BlockNotDisqualifiedFromGC(dev,bi))		{			dirtiest = b;			pagesInUse = (bi->pagesInUse - bi->softDeletions);		}	}		dev->currentDirtyChecker = b;		if(dirtiest > 0)	{		T(YAFFS_TRACE_GC,(TSTR("GC Selected block %d with %d free" TENDSTR),dirtiest,dev->nChunksPerBlock - pagesInUse));	}		dev->oldestDirtySequence = 0; // clear this		if(dirtiest > 0)	{		nonAggressiveSkip = 4;	}	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)		{			dev->nErasureFailures++;			T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Erasure failed %d" TENDSTR),blockNo));		}	}	if(erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE))	{			int i;			for(i = 0; i < dev->nChunksPerBlock; i++)			{					if(!yaffs_CheckChunkErased(dev,blockNo * dev->nChunksPerBlock + i))					{						T(YAFFS_TRACE_ERROR,(TSTR(">>Block %d erasure supposedly OK, but chunk %d not erased" TENDSTR),blockNo,i));

⌨️ 快捷键说明

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