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

📄 yaffs_guts.c

📁 YAFFS
💻 C
📖 第 1 页 / 共 5 页
字号:
static void yaffs_SoftDeleteFile(yaffs_Object * obj){	if (obj->deleted &&	    obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) {		if (obj->nDataChunks <= 0) {			/* Empty file with no duplicate object headers, 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. */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);	}}#endifstatic 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;	}}static 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;				}			}		}	}	return n;}static void yaffs_HashObject(yaffs_Object * in){	int bucket = yaffs_HashFunction(in->objectId);	yaffs_Device *dev = in->myDev;	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 one if it is defered free */				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;	if (number < 0) {		number = yaffs_CreateNewObjectNumber(dev);	}	theObject = yaffs_AllocateEmptyObject(dev);	if (theObject) {		theObject->fake = 0;		theObject->renameAllowed = 1;		theObject->unlinkAllowed = 1;		theObject->objectId = number;		yaffs_HashObject(theObject);		theObject->variantType = type;#ifdef CONFIG_YAFFS_WINCE		yfsd_WinFileTimeNow(theObject->win_atime);		theObject->win_ctime[0] = theObject->win_mtime[0] =		    theObject->win_atime[0];		theObject->win_ctime[1] = theObject->win_mtime[1] =		    theObject->win_atime[1];#else		theObject->yst_atime = theObject->yst_mtime =		    theObject->yst_ctime = Y_CURRENT_TIME;#endif		switch (type) {		case YAFFS_OBJECT_TYPE_FILE:			theObject->variant.fileVariant.fileSize = 0;			theObject->variant.fileVariant.scannedFileSize = 0;			theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF;	/* max __u32 */			theObject->variant.fileVariant.topLevel = 0;			theObject->variant.fileVariant.top =			    yaffs_GetTnode(dev);			break;		case YAFFS_OBJECT_TYPE_DIRECTORY:			INIT_LIST_HEAD(&theObject->variant.directoryVariant.				       children);			break;		case YAFFS_OBJECT_TYPE_SYMLINK:		case YAFFS_OBJECT_TYPE_HARDLINK:		case YAFFS_OBJECT_TYPE_SPECIAL:			/* No action required */			break;		case YAFFS_OBJECT_TYPE_UNKNOWN:			/* todo this should not happen */			break;		}	}	return theObject;}static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev,						      int number,						      yaffs_ObjectType type){	yaffs_Object *theObject = NULL;	if (number > 0) {		theObject = yaffs_FindObjectByNumber(dev, number);	}	if (!theObject) {		theObject = yaffs_CreateNewObject(dev, number, type);	}	return theObject;}static YCHAR *yaffs_CloneString(const YCHAR * str){	YCHAR *newStr = NULL;	if (str && *str) {		newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR));		yaffs_strcpy(newStr, str);	}	return newStr;}/* * Mknod (create) a new object. * equivalentObject only has meaning for a hard link; * aliasString only has meaning for a sumlink. * rdev only has meaning for devices (a subset of special objects) */ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,				       yaffs_Object * parent,				       const YCHAR * name,				       __u32 mode,				       __u32 uid,				       __u32 gid,				       yaffs_Object * equivalentObject,				       const YCHAR * aliasString, __u32 rdev){	yaffs_Object *in;	yaffs_Device *dev = parent->myDev;	/* Check if the entry exists. If it does then fail the call since we don't want a dup.*/	if (yaffs_FindObjectByName(parent, name)) {		return NULL;	}	in = yaffs_CreateNewObject(dev, -1, type);	if (in) {		in->chunkId = -1;		in->valid = 1;		in->variantType = type;		in->yst_mode = mode;#ifdef CONFIG_YAFFS_WINCE		yfsd_WinFileTimeNow(in->win_atime);		in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];		in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];#else		in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;		in->yst_rdev = rdev;		in->yst_uid = uid;		in->yst_gid = gid;#endif		in->nDataChunks = 0;

⌨️ 快捷键说明

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