📄 yaffs_guts.c
字号:
{ 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 outstatic 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->st_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 liststatic void yaffs_FreeObject(yaffs_Object *tn){ yaffs_Device *dev = tn->myDev; yaffs_UnhashObject(tn); // Link into the free list. tn->siblings.next = (struct list_head *)(dev->freeObjects); dev->freeObjects = tn; dev->nFreeObjects++;}static void yaffs_DeinitialiseObjects(yaffs_Device *dev){ // Free the list of allocated Objects while( dev->allocatedObjectList) { YFREE(dev->allocatedObjectList->objects); dev->allocatedObjectList = dev->allocatedObjectList->next; } 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) { 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->st_atime = theObject->st_mtime = theObject->st_ctime = CURRENT_TIME;#endif switch(type) { case YAFFS_OBJECT_TYPE_FILE: theObject->variant.fileVariant.fileSize = 0; theObject->variant.fileVariant.scannedFileSize = 0; 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: // No action required break; case YAFFS_OBJECT_TYPE_HARDLINK: // No action required break; case YAFFS_OBJECT_TYPE_SPECIAL: // No action required break; case YAFFS_OBJECT_TYPE_UNKNOWN: // todo this should not happen break; } } return theObject;}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;}char *yaffs_CloneString(const char *str){ char *newStr = NULL; if(str && *str) { newStr = YMALLOC(strlen(str) + 1); 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)yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, yaffs_Object *parent, const char *name, __u32 mode, __u32 uid, __u32 gid, yaffs_Object *equivalentObject, const char *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->st_mode = mode; #ifdef CONFIG_YAFFS_WINCE yfsd_WinFileTimeNow(in->win_atime); in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -