?? yaffs_guts.c
字號:
int allDone = 1; if (tn) { if (level > 0) { for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0; i--) { if (tn->internal[i]) { if (limit && (*limit) < 0) { allDone = 0; } else { allDone = yaffs_DeleteWorker(in, tn-> internal [i], level - 1, (chunkOffset << YAFFS_TNODES_INTERNAL_BITS) + i, limit); } if (allDone) { yaffs_FreeTnode(dev, tn-> internal[i]); tn->internal[i] = NULL; } } } return (allDone) ? 1 : 0; } else if (level == 0) { int hitLimit = 0; for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit; i--) { theChunk = yaffs_GetChunkGroupBase(dev,tn,i); if (theChunk) { chunkInInode = (chunkOffset << YAFFS_TNODES_LEVEL0_BITS) + i; foundChunk = yaffs_FindChunkInGroup(dev, theChunk, &tags, in->objectId, chunkInInode); if (foundChunk > 0) { yaffs_DeleteChunk(dev, foundChunk, 1, __LINE__); in->nDataChunks--; if (limit) { *limit = *limit - 1; if (*limit <= 0) { hitLimit = 1; } } } yaffs_PutLevel0Tnode(dev,tn,i,0); } } return (i < 0) ? 1 : 0; } } return 1;}static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk){ yaffs_BlockInfo *theBlock; T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk)); theBlock = yaffs_GetBlockInfo(dev, chunk / dev->nChunksPerBlock); if (theBlock) { theBlock->softDeletions++; dev->nFreeChunks++; }}/* 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 theChunk; int allDone = 1; yaffs_Device *dev = in->myDev; 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(dev, 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--) { theChunk = yaffs_GetChunkGroupBase(dev,tn,i); if (theChunk) { /* Note this does not find the real chunk, only the chunk group. * We make an assumption that a chunk group is not larger than * a block. */ yaffs_SoftDeleteChunk(dev, theChunk); yaffs_PutLevel0Tnode(dev,tn,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 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)); list = YMALLOC(sizeof(yaffs_ObjectList)); if (!newObjects || !list) { if(newObjects) YFREE(newObjects); if(list) YFREE(list); 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 ylist_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->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;#ifdef VALGRIND_TEST tn = YMALLOC(sizeof(yaffs_Object));#else /* 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--; }#endif if(tn){ /* Now sweeten it up... */ memset(tn, 0, sizeof(yaffs_Object)); tn->beingCreated = 1; tn->myDev = dev; tn->hdrChunk = 0; tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; YINIT_LIST_HEAD(&(tn->hardLinks)); YINIT_LIST_HEAD(&(tn->hashLink)); YINIT_LIST_HEAD(&tn->siblings); /* Now make the directory sane */ if(dev->rootDir){ tn->parent = dev->rootDir; ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children); } /* 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); } tn->beingCreated = 0; } dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ 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 might have 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->hdrChunk = 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 (!ylist_empty(&tn->hashLink)) { ylist_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; if(tn->parent) YBUG(); if(!ylist_empty(&tn->siblings)) YBUG();#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);#ifdef VALGRIND_TEST YFREE(tn);#else /* Link into the free list. */ tn->siblings.next = (struct ylist_head *)(dev->freeObjects); dev->freeObjects = tn; dev->nFreeObjects++;#endif dev->nCheckpointBlocksRequired = 0; /* force recalculation*/}#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++) { YINIT_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. */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -