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

📄 yaffs_guts.c

📁 把将yaffs 移植到 ucos 系统
💻 C
📖 第 1 页 / 共 5 页
字号:

	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->yst_atime = theObject->yst_mtime =	theObject->yst_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;

}

char *yaffs_CloneString(const char *str)
{
	char *newStr = NULL;
	
	if(str && *str)
	{
		newStr = YMALLOC(strlen(str) + 1);
		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 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->yst_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->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;
		in->yst_rdev  = rdev;
		in->yst_uid   = uid;
		in->yst_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_SPECIAL,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;
}


#if 0
//defined but not used
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;
}

#endif

#if 0
void 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->internalEndBlock - dev->internalStartBlock + 1;
	}
	else
	{
		iterations = dev->internalEndBlock - dev->internalStartBlock + 1;
		iterations = iterations / 16;
		if(iterations > 200)
		{
			iterations = 200;
		}
	}
	
	for(i = 0; i <= iterations && pagesInUse > 0 ; i++)
	{
		b++;
		if ( b < dev->internalStartBlock || b > dev->internalEndBlock)
		{
			b =  dev->internalStartBlock;
		}

		if(b < dev->internalStartBlock || b > dev->internalEndBlock)
		{
			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->internalStartBlock; i <= dev->internalEndBlock; i++)
	{
		dev->allocationBlockFinder++;
		if(dev->allocationBlockFinder <dev->internalStartBlock || dev->allocationBlockFinder> dev->internalEndBlock) 
		{
			dev->allocationBlockFinder = dev->internalStartBlock;
		}
		
		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)
	{

⌨️ 快捷键说明

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