📄 yaffs_guts.c
字号:
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 + -