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

📄 yaffs_guts.c

📁 把将yaffs 移植到 ucos 系统
💻 C
📖 第 1 页 / 共 5 页
字号:
			    	tn->level0[i] = 0;
			    }
		    
			}
			return (i < 0) ? 1 : 0;

			
		}
		
	}
	
	return 1;
	
}

// SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
// All soft deleting does is increment the block's softdelete count and pulls the chunk out
// of the tnode.
// THus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
//
static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset)
{
	int i;
//	int chunkInInode;  	// unused
	int theChunk;
	yaffs_BlockInfo *theBlock;
//	yaffs_Tags tags;	// unused
//	int found;
//	int chunkDeleted;
	int allDone = 1;
	
	
	if(tn)
	{
		if(level > 0)
		{
		
			for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--)
			{
			    if(tn->internal[i])
		    	{
						allDone = yaffs_SoftDeleteWorker(in,tn->internal[i],level - 1,
										(chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i);
					if(allDone)
					{
						yaffs_FreeTnode(in->myDev,tn->internal[i]);
			    		tn->internal[i] = NULL;
					}
					else
					{
						//Hoosterman... how could this happen.
					}			    
				}		    
			}
			return (allDone) ? 1 : 0;
		}
		else if(level == 0)
		{
			
			for(i = YAFFS_NTNODES_LEVEL0 -1; i >=0; i--)
			{
			    if(tn->level0[i])
		    	{
					// Note this does not find the real chunk, only the chunk group.
					// We make an assumption that a chunk group is niot larger than a block.
					theChunk =  (tn->level0[i] << in->myDev->chunkGroupBits);
					T(YAFFS_TRACE_SCAN,(TSTR("soft delete tch %d cgb %d chunk %d" TENDSTR),
						tn->level0[i],in->myDev->chunkGroupBits,theChunk));
						
					theBlock =	yaffs_GetBlockInfo(in->myDev,  theChunk/in->myDev->nChunksPerBlock);
					if(theBlock)
					{
						theBlock->softDeletions++;
					}
			    	tn->level0[i] = 0;
			    }
		    
			}
			return 1;
			
		}
		
	}
	
	return 1;
		
}



static void yaffs_SoftDeleteFile(yaffs_Object *obj)
{
	if(obj->deleted &&
	   obj->variantType == YAFFS_OBJECT_TYPE_FILE &&
	   !obj->softDeleted)
	{
		if(obj->nDataChunks <= 0)
		{
				// Empty file, just delete it immediately
				yaffs_FreeTnode(obj->myDev,obj->variant.fileVariant.top);
				obj->variant.fileVariant.top = NULL;
				T(YAFFS_TRACE_TRACING,(TSTR("yaffs: Deleting empty file %d" TENDSTR),obj->objectId));
				yaffs_DoGenericObjectDeletion(obj);	
		}
		else
		{
			yaffs_SoftDeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0);
			obj->softDeleted = 1;
		}
	}
}





// Pruning removes any part of the file structure tree that is beyond the
// bounds of the file (ie that does not point to chunks).
//
// A file should only get pruned when its size is reduced.
//
// Before pruning, the chunks must be pulled from the tree and the
// level 0 tnode entries must be zeroed out.
// Could also use this for file deletion, but that's probably better handled
// by a special case.

// yaffs_PruneWorker should only be called by yaffs_PruneFileStructure()

static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, __u32 level, int del0)
{
	int i;
	int hasData;
	
	if(tn)
	{
		hasData = 0;
		
		for(i = 0; i < YAFFS_NTNODES_INTERNAL; i++)
		{
		    if(tn->internal[i] && level > 0)
		    {
		    	tn->internal[i] = yaffs_PruneWorker(dev,tn->internal[i],level - 1, ( i == 0) ? del0 : 1);
		    }
		    
		    if(tn->internal[i])
		    {
		    	hasData++;
			}
		}
		
		if(hasData == 0 && del0)
		{
			// Free and return NULL
			
			yaffs_FreeTnode(dev,tn);
			tn = NULL;
		}
		
	}

	return tn;
	
}

static int yaffs_PruneFileStructure(yaffs_Device *dev, yaffs_FileStructure *fStruct)
{
	int i;
	int hasData;
	int done = 0;
	yaffs_Tnode *tn;
	
	if(fStruct->topLevel > 0)
	{
		fStruct->top = yaffs_PruneWorker(dev,fStruct->top, fStruct->topLevel,0);
		
		// Now we have a tree with all the non-zero branches NULL but the height
		// is the same as it was.
		// Let's see if we can trim internal tnodes to shorten the tree.
		// We can do this if only the 0th element in the tnode is in use 
		// (ie all the non-zero are NULL)
		
		while(fStruct->topLevel && !done)
		{
			tn = fStruct->top;
			
			hasData = 0;
			for(i = 1; i <YAFFS_NTNODES_INTERNAL; i++)
			{
				if(tn->internal[i])
		    	{
		    		hasData++;
				}
			}
			
			if(!hasData)
			{
				fStruct->top = tn->internal[0];
				fStruct->topLevel--;
				yaffs_FreeTnode(dev,tn);
			}
			else
			{
				done = 1;
			}
		}
	}
	
	return YAFFS_OK;
}





/////////////////////// End of File Structure functions. /////////////////

// yaffs_CreateFreeObjects creates a bunch more objects and
// adds them to the object free list.
static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
{
    int i;
    yaffs_Object *newObjects;
    yaffs_ObjectList *list;
    
    if(nObjects < 1) return YAFFS_OK;
   
	// make these things
	
    newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
   
    if (!newObjects)
    {
		T(YAFFS_TRACE_ALLOCATE,(TSTR("yaffs: Could not allocate more objects" TENDSTR)));
		return YAFFS_FAIL;
    }
    
    // Hook them into the free list
    for(i = 0; i < nObjects - 1; i++)
    {
    	newObjects[i].siblings.next = (struct list_head *)(&newObjects[i+1]);
    }
    	
	newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
	dev->freeObjects = newObjects;
	dev->nFreeObjects+= nObjects;
	dev->nObjectsCreated+= nObjects;
	
	// Now add this bunch of Objects to a list for freeing up.
	
	list = YMALLOC(sizeof(yaffs_ObjectList));
	if(!list)
	{
		T(YAFFS_TRACE_ALLOCATE,(TSTR("Could not add objects to management list" TENDSTR)));
	}
	else
	{
		list->objects = newObjects;
		list->next = dev->allocatedObjectList;
		dev->allocatedObjectList = list;
	}
	
	
	
	return YAFFS_OK;
}


// AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out
static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)
{
	yaffs_Object *tn = NULL;
	
	// If there are none left make more
	if(!dev->freeObjects)
	{
		yaffs_CreateFreeObjects(dev,YAFFS_ALLOCATION_NOBJECTS);
	}
	
	if(dev->freeObjects)
	{
		tn = dev->freeObjects;
		dev->freeObjects = (yaffs_Object *)(dev->freeObjects->siblings.next);
		dev->nFreeObjects--;
		
		// Now sweeten it up...
	
		memset(tn,0,sizeof(yaffs_Object));
		tn->myDev = dev;
		tn->chunkId = -1;
		tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
		INIT_LIST_HEAD(&(tn->hardLinks));
		INIT_LIST_HEAD(&(tn->hashLink));
		INIT_LIST_HEAD(&tn->siblings);
		
		// Add it to the lost and found directory.
		// NB Can't put root or lostNFound in lostNFound so
		// check if lostNFound exists first
		if(dev->lostNFoundDir)
		{
			yaffs_AddObjectToDirectory(dev->lostNFoundDir,tn);	
		}
	}
	

	return tn;
}

static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev,int number,__u32 mode)
{

	yaffs_Object *obj = yaffs_CreateNewObject(dev,number,YAFFS_OBJECT_TYPE_DIRECTORY);		
	if(obj)
	{
		obj->fake = 1;			// it is fake so it has no NAND presence...
		obj->renameAllowed= 0;	// ... and we're not allowed to rename it...
		obj->unlinkAllowed= 0;	// ... or unlink it
		obj->deleted = 0;
		obj->unlinked = 0;
		obj->yst_mode = mode;
		obj->myDev = dev;
		obj->chunkId = 0; // Not a valid chunk.
	}
	
	return obj;
	
}


static void yaffs_UnhashObject(yaffs_Object *tn)
{
	int bucket;
	yaffs_Device *dev = tn->myDev;
	
	
	// If it is still linked into the bucket list, free from the list
	if(!list_empty(&tn->hashLink))
	{
		list_del_init(&tn->hashLink);
		bucket =  yaffs_HashFunction(tn->objectId);
		dev->objectBucket[bucket].count--;
	}
	
}


// FreeObject frees up a Object and puts it back on the free list
static void yaffs_FreeObject(yaffs_Object *tn)
{

	yaffs_Device *dev = tn->myDev;
	
#ifdef  __KERNEL__
	if(tn->myInode)
	{
		// We're still hooked up to a cached inode.
		// Don't delete now, but mark for later deletion
		tn->deferedFree = 1;
		return;
	}
#endif
	
	yaffs_UnhashObject(tn);
	
	// Link into the free list.
	tn->siblings.next = (struct list_head *)(dev->freeObjects);
	dev->freeObjects = tn;
	dev->nFreeObjects++;
}


#ifdef __KERNEL__

void yaffs_HandleDeferedFree(yaffs_Object *obj)
{
	if(obj->deferedFree)
	{
	   yaffs_FreeObject(obj);
	}
}

#endif



static void yaffs_DeinitialiseObjects(yaffs_Device *dev)
{
	// Free the list of allocated Objects
	
	yaffs_ObjectList *tmp;
	
	while( dev->allocatedObjectList)
	{
		tmp =  dev->allocatedObjectList->next;
		YFREE(dev->allocatedObjectList->objects);
		YFREE(dev->allocatedObjectList);
		
		dev->allocatedObjectList =  tmp;
	}
	
	dev->freeObjects = NULL;
	dev->nFreeObjects = 0;
}

static void yaffs_InitialiseObjects(yaffs_Device *dev)
{
	int i;
	
	dev->allocatedObjectList = NULL;
	dev->freeObjects = NULL;
	dev->nFreeObjects = 0;
	
	for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++)
	{
		INIT_LIST_HEAD(&dev->objectBucket[i].list);
		dev->objectBucket[i].count = 0;	
	}

}






int yaffs_FindNiceObjectBucket(yaffs_Device *dev)
{
	static int x = 0;
	int i;
	int l = 999;
	int lowest = 999999;

		
	// First let's see if we can find one that's empty.
	
	for(i = 0; i < 10 && lowest > 0; i++)
	 {
		x++;
		x %=  YAFFS_NOBJECT_BUCKETS;
		if(dev->objectBucket[x].count < lowest)
		{
			lowest = dev->objectBucket[x].count;
			l = x;
		}
		
	}
	
	// If we didn't find an empty list, then try
	// looking a bit further for a short one
	
	for(i = 0; i < 10 && lowest > 3; i++)
	 {
		x++;
		x %=  YAFFS_NOBJECT_BUCKETS;
		if(dev->objectBucket[x].count < lowest)
		{
			lowest = dev->objectBucket[x].count;
			l = x;
		}
		
	}
	
	return l;
}

static int yaffs_CreateNewObjectNumber(yaffs_Device *dev)
{
	int bucket = yaffs_FindNiceObjectBucket(dev);
	
	// Now find an object value that has not already been taken
	// by scanning the list.
	
	int found = 0;
	struct list_head *i;
	
	__u32 n = (__u32)bucket;

	//yaffs_CheckObjectHashSanity();	
	
	while(!found)
	{
		found = 1;
		n +=  YAFFS_NOBJECT_BUCKETS;
		if(1 ||dev->objectBucket[bucket].count > 0)
		{
			list_for_each(i,&dev->objectBucket[bucket].list)
			{
				// If there is already one in the list
				if(i && list_entry(i, yaffs_Object,hashLink)->objectId == n)
				{
					found = 0;
				}
			}
		}
	}
	
	//T(("bucket %d count %d inode %d\n",bucket,yaffs_objectBucket[bucket].count,n);
	
	return n;	
}

void yaffs_HashObject(yaffs_Object *in)
{
	int bucket = yaffs_HashFunction(in->objectId);
	yaffs_Device *dev = in->myDev;
	
	if(!list_empty(&in->hashLink))
	{
		//YINFO("!!!");
	}

	
	list_add(&in->hashLink,&dev->objectBucket[bucket].list);
	dev->objectBucket[bucket].count++;

}

yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number)
{
	int bucket = yaffs_HashFunction(number);
	struct list_head *i;
	yaffs_Object *in;
	
	list_for_each(i,&dev->objectBucket[bucket].list)
	{
		// Look if it is in the list
		if(i)
		{
			in = list_entry(i, yaffs_Object,hashLink);
			if(in->objectId == number)
			{
#ifdef __KERNEL__
				// Don't tell the VFS about this if it has been marked for freeing
 				if(in->deferedFree) 
				    return NULL;
#endif
				return in;
			}
		}
	}
	
	return NULL;
}



yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type)
{
		
	yaffs_Object *theObject;

⌨️ 快捷键说明

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