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

📄 yaffs_guts.c

📁 yaffs2
💻 C
📖 第 1 页 / 共 5 页
字号:
{	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_SPECIAL, 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);}/* 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 shadows){	int unlinkOp;	int deleteOp;	yaffs_Object *existingTarget;	if (newDir == NULL) {		newDir = obj->parent;	/* use the old directory */	}	if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {		T(YAFFS_TRACE_ALWAYS,		  (TSTR		   ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"		    TENDSTR)));		YBUG();	}		/* 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);	existingTarget = yaffs_FindObjectByName(newDir, newName);	/* 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.	 *   else only proceed if the new name does not exist and if we're putting 	 *   it into a directory.	 */	if ((unlinkOp ||	     deleteOp ||	     force ||	     (shadows > 0) ||	     !existingTarget) &&	    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 deletion then we mark it as a shrink for gc purposes. */		if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 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;	yaffs_Object *existingTarget;	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);	/* Check new name to long. */	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&	    yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)	  /* ENAMETOOLONG */	  return YAFFS_FAIL;	else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&		 yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)	  /* ENAMETOOLONG */	  return YAFFS_FAIL;	if (obj && obj->renameAllowed) {		/* Now do the handling for an existing target, if there is one */		existingTarget = yaffs_FindObjectByName(newDir, newName);		if (existingTarget &&		    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&		    !list_empty(&existingTarget->variant.directoryVariant.children)) {			/* There is a target that is a non-empty directory, so we fail */			return YAFFS_FAIL;	/* EEXIST or ENOTEMPTY */		} else if (existingTarget && existingTarget != obj) {			/* Nuke the target first, using shadowing, 			 * but only if it isn't the same object			 */			yaffs_ChangeObjectName(obj, newDir, newName, force,					       existingTarget->objectId);			yaffs_UnlinkObject(existingTarget);		}		return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0);	}	return YAFFS_FAIL;}/*------------------------- Block Management and Page Allocation ----------------*/static int yaffs_InitialiseBlocks(yaffs_Device * dev){	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;		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));	if(!dev->blockInfo){		dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo));		dev->blockInfoAlt = 1;	}	else		dev->blockInfoAlt = 0;		/* Set up dynamic blockinfo stuff. */	dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; // round up bytes	dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);	if(!dev->chunkBits){		dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);		dev->chunkBitsAlt = 1;	}	else		dev->chunkBitsAlt = 0;		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){	if(dev->blockInfoAlt)		YFREE_ALT(dev->blockInfo);	else		YFREE(dev->blockInfo);	dev->blockInfoAlt = 0;	dev->blockInfo = NULL;		if(dev->chunkBitsAlt)		YFREE_ALT(dev->chunkBits);	else		YFREE(dev->chunkBits);	dev->chunkBitsAlt = 0;	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->internalStartBlock; i <= dev->internalEndBlock;		     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->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 0		if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {			dirtiest = b;			pagesInUse = 0;		}		else #endif		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;	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) {		yaffs_InvalidateCheckpoint(dev);		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));			}		}	}	if (erasedOk) {		/* Clean it up... */		bi->blockState = YAFFS_BLOCK_STATE_EMPTY;		dev->nErasedBlocks++;		bi->pagesInUse = 0;		bi->softDeletions = 0;		bi->hasShrinkHeader = 0;		yaffs_ClearChunkBits(dev, blockNo);		T(YAFFS_TRACE_ERASE,		  (TSTR("Erased block %d" TENDSTR), blockNo));	} else {		dev->nFreeChunks -= dev->nChunksPerBlock;	/* We lost a block of free space */		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 more eraased blocks" 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->sequenceNumber++;			bi->sequenceNumber = dev->sequenceNumber;			dev->nErasedBlocks--;			T(YAFFS_TRACE_ALLOCATE,			  (TSTR("Allocated block %d, seq  %d, %d left" TENDSTR),			   dev->allocationBlockFinder, dev->sequenceNumber,			   dev->nErasedBlocks));			return dev->allocationBlockFinder;		}	}	T(YAFFS_TRACE_ALWAYS,	  (TSTR	   ("yaffs tragedy: no more eraased blocks, but there should have been %d"	    TENDSTR), dev->nErasedBlocks));	return -1;}// Check if there's space to allocate...// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev){	int reservedChunks;	int reservedBlocks = dev->nReservedBlocks;	int checkpointBlocks;		checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;	if(checkpointBlocks < 0)		checkpointBlocks = 0;		reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);		return (dev->nFreeChunks > reservedChunks);}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 && !yaffs_CheckSpaceForAllocation(dev)) {		/* Not enough space to allocate unless we're allowed to use the reserve. */		return -1;	}	if (dev->nErasedBlocks < dev->nReservedBlocks	    && dev->allocationPage == 0) {		T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR)));	}	/* 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;}static int yaffs_GetErasedChunks(yaffs_Device * dev){	int n;	n = dev->nErasedBlocks * dev->nChunksPerBlock;	if (dev->allocationBlock > 0) {		n += (dev->nChunksPerBlock - dev->allocationPage);	}	return n;}static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block){	int oldChunk;	int newChunk;	int chunkInBlock;	int markNAND;	int retVal = YAFFS_OK;	int cleanups = 0;	int i;	int isCheckpointBlock;	int chunksBefore = yaffs_GetErasedChunks(dev);	int chunksAfter;	yaffs_ExtendedTags tags;	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, block);	yaffs_Object *object;

⌨️ 快捷键说明

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