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

📄 yaffs_guts.c

📁 yaffs2设备驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
		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;		bi->skipErasedCheck = 1;  /* This is clean, so no need to check */		bi->gcPrioritise = 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, yaffs_BlockInfo **blockUsedPtr){	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;		}		if(blockUsedPtr)			*blockUsedPtr = bi;					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;	isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);		bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;	T(YAFFS_TRACE_TRACING,	  (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,	   bi->pagesInUse, bi->hasShrinkHeader));	/*yaffs_VerifyFreeChunks(dev); */	bi->hasShrinkHeader = 0;	/* clear the flag so that the block can erase */	/* Take off the number of soft deleted entries because	 * they're going to get really deleted during GC.	 */	dev->nFreeChunks -= bi->softDeletions;	dev->isDoingGC = 1;	if (isCheckpointBlock ||	    !yaffs_StillSomeChunkBits(dev, block)) {		T(YAFFS_TRACE_TRACING,		  (TSTR		   ("Collecting block %d that has no chunks in use" TENDSTR),		   block));		yaffs_BlockBecameDirty(dev, block);	} else {		__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);		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;				yaffs_InitialiseTags(&tags);				yaffs_ReadChunkWithTagsFromNAND(dev, oldChunk,								buffer, &tags);				object =				    yaffs_FindObjectByNumber(dev,							     tags.objectId);				T(YAFFS_TRACE_GC_DETAIL,				  (TSTR				   ("Collecting page %d, %d %d %d " TENDSTR),				   chunkInBlock, tags.objectId, tags.chunkId,				   tags.byteCount));				if (!object) {					T(YAFFS_TRACE_ERROR,					  (TSTR					   ("page %d in gc has no object "					    TENDSTR), oldChunk));				}				if (object && object->deleted				    && tags.chunkId != 0) {					/* Data chunk in a deleted file, throw it away					 * It's a soft deleted data chunk,					 * No need to copy this, just forget about it and 					 * fix up the object.					 */					object->nDataChunks--;					if (object->nDataChunks <= 0) {						/* remeber to clean up the object */						dev->gcCleanupList[cleanups] =						    tags.objectId;						cleanups++;					}					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++;					dev->nGCCopies++;					if (tags.chunkId == 0) {						/* It is an object Id,						 * We need to nuke the shrinkheader flags first						 * We no longer want the shrinkHeader flag since its work is done						 * and if it is left in place it will mess up scanning.						 * Also, clear out any shadowing stuff						 */						yaffs_ObjectHeader *oh;						oh = (yaffs_ObjectHeader *)buffer;						oh->isShrink = 0;						oh->shadowsObject = -1;						tags.extraShadows = 0;						tags.extraIsShrinkHeader = 0;					}					newChunk =					    yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags, 1);					if (newChunk < 0) {						retVal = YAFFS_FAIL;					} else {						/* 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);						}					}				}				yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);			}		}		yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);		/* Do any required cleanups */		for (i = 0; i < cleanups; i++) {			/* Time to delete the file too */			object =			    yaffs_FindObjectByNumber(dev,						     dev->gcCleanupList[i]);			if (object) {				yaffs_FreeTnode(dev,						object->variant.fileVariant.						top);				object->variant.fileVariant.top = NULL;				T(YAFFS_TRACE_GC,				  (TSTR				   ("yaffs: About to finally delete object %d"				    TENDSTR), object->objectId));				yaffs_DoGenericObjectDeletion(object);				object->myDev->nDeletedFiles--;			}		}	}	if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {		T(YAFFS_TRACE_GC,		  (TSTR		   ("gc did not increase free chunks before %d after %d"		    TENDSTR), chunksBefore, chunksAfter));	}	dev->isDoingGC = 0;	return YAFFS_OK;}/* New garbage collector * If we're very low on erased blocks then we do aggressive garbage collection * otherwise we do "leasurely" garbage collection. * Aggressive gc looks further (whole array) and will accept less dirty blocks. * Passive gc only inspects smaller areas and will only accept more dirty blocks. * * The idea is to help clear out space in a more spread-out manner. * Dunno if it really does anything useful. */static int yaffs_CheckGarbageCollection(yaffs_Device * dev){	int block;	int aggressive;	int gcOk = YAFFS_OK;	int maxTries = 0;		int checkpointBlockAdjust;	if (dev->isDoingGC) {		/* Bail out so we don't get recursive gc */		return YAFFS_OK;	}		/* This loop should pass the first time.	 * We'll only see looping here if the erase of the collected block fails.	 */	do {		maxTries++;				checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);		if(checkpointBlockAdjust < 0)			checkpointBlockAdjust = 0;		if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) {			/* We need a block soon...*/			aggressive = 1;		} else {			/* We're in no hurry */			aggressive = 0;		}		block = yaffs_FindBlockForGarbageCollection(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));			gcOk = yaffs_GarbageCollectBlock(dev, block);		}		if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {			T(YAFFS_TRACE_GC,			  (TSTR			   ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"			    TENDSTR), dev->nErasedBlocks, maxTries, block));		}	} while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)		 && (maxTries < 2));	return aggressive ? gcOk : YAFFS_OK;}/*-------------------------  TAGS --------------------------------*/static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,			   int chunkInObject){	return (tags->chunkId == chunkInObject &&		tags->objectId == objectId && !tags->chunkDeleted) ? 1 : 0;}/*-------------------- Data file manipulation -----------------*/static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,				 yaffs_ExtendedTags * tags){	/*Get the Tnode, then get the level 0 offset chunk offset */	yaffs_Tnode *tn;	int theChunk = -1;	yaffs_ExtendedTags localTags;	int retVal = -1;	yaffs_Device *dev = in->myDev;	if (!tags) {		/* Passed a NULL, so use our own tags space */		tags = &localTags;	}	tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);	if (tn) {		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);		retVal =		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,					   chunkInInode);	}	return retVal;}static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode,					  yaffs_ExtendedTags * tags){	/* Get the Tnode, then get the level 0 offset chunk offset */	yaffs_Tnode *tn;	int theChunk = -1;	yaffs_ExtendedTags localTags;	yaffs_Device *dev = in->myDev;	int retVal = -1;	if (!tags) {		/* Passed a NULL, so use our own tags space */		tags = &localTags;	}	tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);	if (tn) {		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);		retVal =		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,					   chunkInInode);		/* Delete the entry in the filestructure (if found) */		if (retVal != -1) {			yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0);		}	} else {		/*T(("No level 0 found for %d\n", chunkInInode)); */	}	if (retVal == -1) {		/* T(("Could not find %d to delete\n",chunkInInode)); */	}	return retVal;}#ifdef YAFFS_PARANOIDstatic int yaffs_CheckFileSanity(yaffs_Object * in){	int chunk;	int nChunks;	int fSize;	int failed = 0;	int objId;	yaffs_Tnode *tn;	yaffs_Tags localTags;	yaffs_Tags *tags = &localTags;	int theChunk;	int chunkDeleted;	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {		/* T(("Objec

⌨️ 快捷键说明

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