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

📄 yaffs_guts.c

📁 把将yaffs 移植到 ucos 系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		// Not enough space to allocate unless we're allowed to use the reserve.
		return -1;
	}
	
	// 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;	
}

// To determine if we have enough space we just look at the 
// number of erased blocks.
// The cache is allowed to use reserved blocks.

static int yaffs_CheckSpaceForChunkCache(yaffs_Device *dev)
{
	return (dev->nErasedBlocks >= dev->nReservedBlocks);
}


static int  yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
{
	int oldChunk;
	int newChunk;
	int chunkInBlock;
	int markNAND;
	
	
	yaffs_Spare spare;
	yaffs_Tags  tags;
	__u8  buffer[YAFFS_BYTES_PER_CHUNK];
	
//	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,block);
	
	yaffs_Object *object;

	//T(("Collecting block %d n %d bits %x\n",block, bi->pagesInUse, bi->pageBits));	
	
	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;
			
			//T(("copying page %x from %d to %d\n",mask,oldChunk,newChunk));
			
			yaffs_ReadChunkFromNAND(dev,oldChunk,buffer, &spare,1);
			
			yaffs_GetTagsFromSpare(dev,&spare,&tags);

			object = yaffs_FindObjectByNumber(dev,tags.objectId);
			
			if(object && object->deleted && tags.chunkId != 0)
			{
				// Data chunk in a deleted file, throw it away
				// It's a deleted data chunk,
				// No need to copy this, just forget about it and fix up the
				// object.
				
				//yaffs_PutChunkIntoFile(object, tags.chunkId, 0,0); 
				object->nDataChunks--;
				
				if(object->nDataChunks <= 0)
				{
					// Time to delete the file too
					yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top);
					object->variant.fileVariant.top = NULL;
					T(YAFFS_TRACE_TRACING,(TSTR("yaffs: About to finally delete object %d" TENDSTR),object->objectId));
					yaffs_DoGenericObjectDeletion(object);					
 				}
				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++;
				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;
}

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

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


#if 0
#define YAFFS_GARBAGE_COLLECT_LOW_WATER 2
static 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 0
static 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);
	
}
#endif


static 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_PARANOID

static 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 

⌨️ 快捷键说明

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