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

📄 yaffs_guts.c

📁 USBONs3c2410.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
				tags.serialNumber++;				yaffs_LoadTagsIntoSpare(&spare,&tags);				dev->nGCCopies++;				newChunk = yaffs_WriteNewChunkToNAND(dev, buffer, &spare,1);							if(newChunk < 0)				{					return YAFFS_FAIL;				}							// 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);								}	}	return YAFFS_OK;}static yaffs_Object *yaffs_FindDeletedUnlinkedFile(yaffs_Device *dev){	// find a file to delete	struct list_head *i;		yaffs_Object *l;	//Scan the unlinked files looking for one to delete	list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children)	{		if(i)		{			l = list_entry(i, yaffs_Object,siblings);			if(l->deleted)			{				return l;						}		}	}		return NULL;}static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev){	// This does background deletion on unlinked files.. only deleted ones.	// If we don't have a file we're working on then find one	if(!dev->unlinkedDeletion && dev->nDeletedFiles > 0)	{		dev->unlinkedDeletion = yaffs_FindDeletedUnlinkedFile(dev);	}		// OK, we're working on a file...	if(dev->unlinkedDeletion)	{		yaffs_Object *obj = dev->unlinkedDeletion;		int delresult;		int limit; // Number of chunks to delete in a file.				   // NB this can be exceeded, but not by much.				   		limit = -1;		delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit);				if(obj->nDataChunks == 0)		{			// Done all the deleting of data chunks.			// Now dump the header and clean up			yaffs_FreeTnode(dev,obj->variant.fileVariant.top);			obj->variant.fileVariant.top = NULL;			yaffs_DoGenericObjectDeletion(obj);			dev->nDeletedFiles--;			dev->nUnlinkedFiles--;			dev->nBackgroundDeletions++;			dev->unlinkedDeletion = NULL;			}	}}#if 0#define YAFFS_GARBAGE_COLLECT_LOW_WATER 2static int yaffs_CheckGarbageCollection(yaffs_Device *dev){	int block;	int aggressive=0;		//yaffs_DoUnlinkedFileDeletion(dev);		if(dev->nErasedBlocks <= (dev->nReservedBlocks + YAFFS_GARBAGE_COLLECT_LOW_WATER))	{		aggressive = 1;	}				if(aggressive)	{		block = yaffs_FindDirtiestBlock(dev,aggressive);				if(block >= 0)		{			dev->garbageCollections++;			return yaffs_GarbageCollectBlock(dev,block);		}			else		{			return YAFFS_FAIL;		}	}	return YAFFS_OK;}#endif// New garbage collector// If we're very low on erased blocks then we do aggressive garbage collection// otherwise we do "passive" garbage collection.// Aggressive gc looks further (whole array) and will accept dirtier blocks.// Passive gc only inspects smaller areas and will only accept cleaner 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=0;		//yaffs_DoUnlinkedFileDeletion(dev);		if(dev->nErasedBlocks <= (dev->nReservedBlocks + 1))	{		aggressive = 1;	}				block = yaffs_FindDirtiestBlock(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));		return yaffs_GarbageCollectBlock(dev,block);	}		return aggressive ? YAFFS_FAIL : YAFFS_OK;}//////////////////////////// TAGS ///////////////////////////////////////static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr){	yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;		yaffs_CalcTagsECC(tagsPtr);		sparePtr->tagByte0 = tu->asBytes[0];	sparePtr->tagByte1 = tu->asBytes[1];	sparePtr->tagByte2 = tu->asBytes[2];	sparePtr->tagByte3 = tu->asBytes[3];	sparePtr->tagByte4 = tu->asBytes[4];	sparePtr->tagByte5 = tu->asBytes[5];	sparePtr->tagByte6 = tu->asBytes[6];	sparePtr->tagByte7 = tu->asBytes[7];}static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr){	yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;	int result;	tu->asBytes[0]= sparePtr->tagByte0;	tu->asBytes[1]= sparePtr->tagByte1;	tu->asBytes[2]= sparePtr->tagByte2;	tu->asBytes[3]= sparePtr->tagByte3;	tu->asBytes[4]= sparePtr->tagByte4;	tu->asBytes[5]= sparePtr->tagByte5;	tu->asBytes[6]= sparePtr->tagByte6;	tu->asBytes[7]= sparePtr->tagByte7;		result =  yaffs_CheckECCOnTags(tagsPtr);	if(result> 0)	{		dev->tagsEccFixed++;	}	else if(result <0)	{		dev->tagsEccUnfixed++;	}}static void yaffs_SpareInitialise(yaffs_Spare *spare){	memset(spare,0xFF,sizeof(yaffs_Spare));}static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_Tags *tags, int *chunkDeleted){	if(tags)	{		yaffs_Spare spare;		if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,NULL,&spare,1) == YAFFS_OK)		{			*chunkDeleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;			yaffs_GetTagsFromSpare(dev,&spare,tags);			return YAFFS_OK;		}		else		{			return YAFFS_FAIL;		}	}		return YAFFS_OK;}#if 0static int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *buffer, yaffs_Tags *tags){	// NB There must be tags, data is optional	// If there is data, then an ECC is calculated on it.		yaffs_Spare spare;		if(!tags)	{		return YAFFS_FAIL;	}		yaffs_SpareInitialise(&spare);		if(!dev->useNANDECC && buffer)	{		yaffs_CalcECC(buffer,&spare);	}		yaffs_LoadTagsIntoSpare(&spare,tags);		return yaffs_WriteChunkToNAND(dev,chunkInNAND,buffer,&spare);	}#endifstatic int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_Tags *tags, int useReserve){	// NB There must be tags, data is optional	// If there is data, then an ECC is calculated on it.		yaffs_Spare spare;		if(!tags)	{		return YAFFS_FAIL;	}		yaffs_SpareInitialise(&spare);		if(!dev->useNANDECC && buffer)	{		yaffs_CalcECC(buffer,&spare);	}		yaffs_LoadTagsIntoSpare(&spare,tags);		return yaffs_WriteNewChunkToNAND(dev,buffer,&spare,useReserve);	}static int yaffs_TagsMatch(const yaffs_Tags *tags, int objectId, int chunkInObject, int chunkDeleted){	return 	(  tags->chunkId == chunkInObject &&			   tags->objectId == objectId &&			   !chunkDeleted) ? 1 : 0;	}int yaffs_FindChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_Tags *tags){	//Get the Tnode, then get the level 0 offset chunk offset    yaffs_Tnode *tn;         int theChunk = -1;    yaffs_Tags localTags;    int i;    int found = 0;    int chunkDeleted;        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 = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->chunkGroupBits;		// Now we need to do the shifting etc and search for it		for(i = 0,found = 0; theChunk && i < dev->chunkGroupSize && !found; i++)		{			yaffs_ReadChunkTagsFromNAND(dev,theChunk,tags,&chunkDeleted);			if(yaffs_TagsMatch(tags,in->objectId,chunkInInode,chunkDeleted))			{				// found it;				found = 1;			}			else			{				theChunk++;			}		}    }    return found ? theChunk : -1;}int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_Tags *tags){	//Get the Tnode, then get the level 0 offset chunk offset    yaffs_Tnode *tn;         int theChunk = -1;    yaffs_Tags localTags;    int i;    int found = 0;    yaffs_Device *dev = in->myDev;    int chunkDeleted;        if(!tags)    {    	// Passed a NULL, so use our own tags space    	tags = &localTags;    }        tn = yaffs_FindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode);        if(tn)    {    		theChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->chunkGroupBits;    		// Now we need to do the shifting etc and search for it		for(i = 0,found = 0; theChunk && i < dev->chunkGroupSize && !found; i++)		{			yaffs_ReadChunkTagsFromNAND(dev,theChunk,tags,&chunkDeleted);			if(yaffs_TagsMatch(tags,in->objectId,chunkInInode,chunkDeleted))			{				// found it;				found = 1;			}			else			{				theChunk++;			}		}    		// Delete the entry in the filestructure		if(found)		{			tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = 0;		}    }    else    {    	//T(("No level 0 found for %d\n", chunkInInode));    }        if(!found)    {    	//T(("Could not find %d to delete\n",chunkInInode));    }    return found ? theChunk : -1;}#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(("Object not a file\n"));		return YAFFS_FAIL;	}		objId = in->objectId;	fSize  = in->variant.fileVariant.fileSize;	nChunks = (fSize + in->myDev->nBytesPerChunk -1)/in->myDev->nBytesPerChunk;		for(chunk = 1; chunk <= nChunks; chunk++)	{		tn = yaffs_FindLevel0Tnode(in->myDev,&in->variant.fileVariant, chunk);    		if(tn)		{    			theChunk = tn->level0[chunk & YAFFS_TNODES_LEVEL0_MASK] << in->myDev->chunkGroupBits;    				yaffs_ReadChunkTagsFromNAND(in->myDev,theChunk,tags,&chunkDeleted);				if(yaffs_TagsMatch(tags,in->objectId,chunk,chunkDeleted))				{					// found it;								}				else				{					//T(("File problem file [%d,%d] NAND %d  tags[%d,%d]\n",					//		objId,chunk,theChunk,tags->chunkId,tags->objectId);												failed = 1;												}    		}		else		{			//T(("No level 0 found for %d\n", chunk));		}	}		return failed ? YAFFS_FAIL : YAFFS_OK;}#endifstatic int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkInNAND, int inScan){	yaffs_Tnode *tn;	yaffs_Device *dev = in->myDev;	int existingChunk;	yaffs_Tags existingTags;	yaffs_Tags newTags;	unsigned existingSerial, newSerial;		int newChunkDeleted;			tn = yaffs_AddOrFindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode);	if(!tn)	{		return YAFFS_FAIL;	}	existingChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK];				if(inScan)	{		// If we're scanning then we need to test for duplicates		// NB This does not need to be efficient since it should only ever 		// happen when the power fails during a write, then only one		// chunk should ever be affected.					if(existingChunk != 0)		{			// NB Right now existing chunk will not be real chunkId if the device >= 32MB			//    thus we have to do a FindChunkInFile to get the real chunk id.			//			// We have a duplicate now we need to decide which one to use			// To do this we get both sets of tags and compare serial numbers.			yaffs_ReadChunkTagsFromNAND(dev,chunkInNAND, &newTags,&newChunkDeleted);									// Do a proper find			existingChunk = yaffs_FindChunkInFile(in,chunkInInode, &existingTags);			if(existingChunk <=0)			{				//Hoosterman - how did this happen?								T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: existing chunk < 0 in scan" TENDSTR)));			}						// NB The deleted flags should be false, otherwise the chunks will 			// not be loaded during a scan						newSerial = newTags.serialNumber;			existingSerial = existingTags.serialNumber;						if( existingChunk <= 0 ||			    ((existingSerial+1) & 3) == newSerial)			{				// Use new				// Delete the old one and drop through to update the tnode				yaffs_DeleteChunk(dev,existingChunk,1);			}			else			{				// Use existing.				// Delete the new one and return early so that the tnode isn't changed				yaffs_DeleteChunk(dev,chunkInNAND,1);				return YAFFS_OK;			}		}	}			if(existingChunk == 0)	{		in->nDataChunks++;	}		tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = (chunkInNAND >> dev->chunkGroupBits);		return YAFFS_OK;}int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffer){    int chunkInNAND = yaffs_FindChunkInFile(in,chunkInInode,NULL);        if(chunkInNAND >= 0)    {		return yaffs_ReadChunkFromNAND(in->myDev,chunkInNAND,buffer,NULL,1);	}	else	{		memset(buffer,0,YAFFS_BYTES_PER_CHUNK);		return 0;	}}static void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND){	int block;	int page;	yaffs_Spare spare;	yaffs_BlockInfo *bi;		if(chunkId <= 

⌨️ 快捷键说明

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