X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=ad033bd156de32ddea25bb1a3337b80122b691bc;hp=02723f71a8e2b691bccb75c7b2f5e1d7dacc41d0;hb=17980527e964732381ef3fe6d1f2946bd9a9cd47;hpb=c6b03b32a79d425c28ac2de255a89135c19f5f15 diff --git a/yaffs_guts.c b/yaffs_guts.c index 02723f7..ad033bd 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -1,4 +1,3 @@ - /* * YAFFS: Yet another FFS. A NAND-flash specific file system. * @@ -14,7 +13,7 @@ */ //yaffs_guts.c -const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.10 2005-07-26 03:05:28 charles Exp $"; +const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.15 2005-08-02 04:24:22 charles Exp $"; #include "yportenv.h" @@ -103,7 +102,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type); static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj); -static int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink); +static int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink, int shadows); static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj); static int yaffs_CheckStructures(void); static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit); @@ -208,7 +207,7 @@ static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device *dev,int blockNo, return yaffs_TagsCompatabilityQueryNANDBlock(dev,blockNo,state,sequenceNumber); } -int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND) +static int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND) { int result; @@ -589,7 +588,7 @@ static __u16 yaffs_CalcNameSum(const YCHAR *name) return sum; } -void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) +static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) { #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM if(name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) @@ -654,13 +653,13 @@ static int yaffs_CreateTnodes(yaffs_Device *dev,int nTnodes) { newTnodes[i].internal[0] = &newTnodes[i+1]; #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG - newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = 1; + newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1; #endif } newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes; #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG - newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = 1; + newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1; #endif dev->freeTnodes = newTnodes; dev->nFreeTnodes+= nTnodes; @@ -705,7 +704,7 @@ static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev) { tn = dev->freeTnodes; #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG - if(tn->internal[YAFFS_NTNODES_INTERNAL] != 1) + if(tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) { // Hoosterman, this thing looks like it isn't in the list T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 1" TENDSTR))); @@ -733,7 +732,7 @@ static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn) // Hoosterman, this thing looks like it is already in the list T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 2" TENDSTR))); } - tn->internal[YAFFS_NTNODES_INTERNAL] = 1; + tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1; #endif tn->internal[0] = dev->freeTnodes; dev->freeTnodes = tn; @@ -969,7 +968,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, yaffs_FileStru } -int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, yaffs_ExtendedTags *tags, int objectId, int chunkInInode) +static int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, yaffs_ExtendedTags *tags, int objectId, int chunkInInode) { int j; @@ -1496,7 +1495,7 @@ static void yaffs_InitialiseObjects(yaffs_Device *dev) -int yaffs_FindNiceObjectBucket(yaffs_Device *dev) +static int yaffs_FindNiceObjectBucket(yaffs_Device *dev) { static int x = 0; int i; @@ -1572,7 +1571,7 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device *dev) return n; } -void yaffs_HashObject(yaffs_Object *in) +static void yaffs_HashObject(yaffs_Object *in) { int bucket = yaffs_HashFunction(in->objectId); yaffs_Device *dev = in->myDev; @@ -1677,7 +1676,7 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectTyp return theObject; } -yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaffs_ObjectType type) +static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaffs_ObjectType type) { yaffs_Object *theObject = NULL; @@ -1695,7 +1694,7 @@ yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaf } -YCHAR *yaffs_CloneString(const YCHAR *str) +static YCHAR *yaffs_CloneString(const YCHAR *str) { YCHAR *newStr = NULL; @@ -1714,7 +1713,7 @@ YCHAR *yaffs_CloneString(const YCHAR *str) // 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, +static yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, yaffs_Object *parent, const YCHAR *name, __u32 mode, @@ -1784,7 +1783,7 @@ yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type, } if(/*yaffs_GetNumberOfFreeChunks(dev) <= 0 || */ - yaffs_UpdateObjectHeader(in,name,0,0) < 0) + yaffs_UpdateObjectHeader(in,name,0,0,0) < 0) { // Could not create the object header, fail the creation yaffs_DestroyObject(in); @@ -1834,10 +1833,12 @@ yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, yaffs_Object * } -static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const YCHAR *newName,int force) +static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const YCHAR *newName,int force,int shadows) { int unlinkOp; int deleteOp; + + yaffs_Object * existingTarget; if(newDir == NULL) { @@ -1862,13 +1863,16 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const deleteOp = (newDir == obj->myDev->deletedDir); + existingTarget = yaffs_FindObjectByName(newDir,newName); + // If the object is a file going into the unlinked directory, then it is OK to just stuff it in since // duplicate names are allowed. // Otherwise only proceed if the new name does not exist and if we're putting it into a directory. if( (unlinkOp|| deleteOp || force || - !yaffs_FindObjectByName(newDir,newName)) && + (shadows > 0) || + !existingTarget) && newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) { yaffs_SetObjectName(obj,newName); @@ -1879,7 +1883,7 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const if(unlinkOp) obj->unlinked = 1; // If it is a deletion then we mark it as a shrink for gc purposes. - if(yaffs_UpdateObjectHeader(obj,newName,0,deleteOp) >= 0) + if(yaffs_UpdateObjectHeader(obj,newName,0,deleteOp,shadows) >= 0) { return YAFFS_OK; } @@ -1893,6 +1897,7 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object *newDir, const YCHAR *newName) { yaffs_Object *obj; + yaffs_Object *existingTarget; int force = 0; #ifdef CONFIG_YAFFS_CASE_INSENSITIVE @@ -1906,9 +1911,29 @@ int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object #endif obj = yaffs_FindObjectByName(oldDir,oldName); + if(obj && obj->renameAllowed) { - return yaffs_ChangeObjectName(obj,newDir,newName,force); + + // Now do the handling for an existing target, if there is one + + existingTarget = yaffs_FindObjectByName(newDir,newName); + if(existingTarget && + existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && + !list_empty(&existingTarget->variant.directoryVariant.children)) + { + // There is a target that is a non-empty directory, so we have to fail + return YAFFS_FAIL; // EEXIST or ENOTEMPTY + } + else if(existingTarget) + { + // Nuke the target first, using shadowing + yaffs_ChangeObjectName(obj,newDir,newName,force,existingTarget->objectId); + yaffs_Unlink(newDir,newName); + } + + + return yaffs_ChangeObjectName(obj,newDir,newName,force,0); } return YAFFS_FAIL; } @@ -2386,7 +2411,7 @@ static int yaffs_GetErasedChunks(yaffs_Device *dev) } -int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) +static int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) { int oldChunk; int newChunk; @@ -2492,6 +2517,18 @@ int yaffs_GarbageCollectBlock(yaffs_Device *dev,int block) tags.serialNumber++; dev->nGCCopies++; + + if(tags.chunkId == 0) + { + // It is an object Id, + // We need to nuke the shrinkheader flags first + // We no longer want the shrinkHeader flag since its work is done + // and if it is left in place it will mess up scanning. + + yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer; + oh->isShrink = 0; + tags.extraIsShrinkHeader = 0; + } newChunk = yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags,1); @@ -2630,7 +2667,7 @@ static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev) // The idea is to help clear out space in a more spread-out manner. // Dunno if it really does anything useful. // -int yaffs_CheckGarbageCollection(yaffs_Device *dev) +static int yaffs_CheckGarbageCollection(yaffs_Device *dev) { int block; int aggressive; @@ -2838,7 +2875,7 @@ static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, int chu ///////////////////////////////////////////////////////////////////////////////////////////////////////// -int yaffs_FindChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags) +static int yaffs_FindChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags) { //Get the Tnode, then get the level 0 offset chunk offset yaffs_Tnode *tn; @@ -2866,7 +2903,7 @@ int yaffs_FindChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags * return retVal; } -int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags) +static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags) { //Get the Tnode, then get the level 0 offset chunk offset yaffs_Tnode *tn; @@ -3093,7 +3130,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkIn -int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffer) +static int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffer) { int chunkInNAND = yaffs_FindChunkInFile(in,chunkInInode,NULL); @@ -3188,7 +3225,7 @@ void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND,int lyn) -int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 *buffer,int nBytes,int useReserve) +static int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 *buffer,int nBytes,int useReserve) { // Find old chunk Need to do this to get serial number // Write new one and patch into tree. @@ -3244,7 +3281,7 @@ int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 * // UpdateObjectHeader updates the header on NAND for an object. // If name is not NULL, then that new name is used. // -int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink) +int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink,int shadows) { yaffs_BlockInfo *bi; @@ -3288,6 +3325,9 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int i oh->type = in->variantType; oh->yst_mode = in->yst_mode; + + // shadowing + oh->shadowsObject = shadows; #ifdef CONFIG_YAFFS_WINCE oh->win_atime[0] = in->win_atime[0]; @@ -3368,6 +3408,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int i newTags.extraFileLength = oh->fileSize; newTags.extraIsShrinkHeader = oh->isShrink; newTags.extraEquivalentObjectId = oh->equivalentObjectId; + newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0; newTags.extraObjectType = in->variantType; // Create new chunk in NAND @@ -3421,7 +3462,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int i static void yaffs_FlushFilesChunkCache(yaffs_Object *obj) { yaffs_Device *dev = obj->myDev; - int lowest; + int lowest = -99; // Stop compiler whining. int i; yaffs_ChunkCache *cache; int chunkWritten = 0; @@ -4086,7 +4127,7 @@ int yaffs_ResizeFile(yaffs_Object *in, int newSize) in->parent->objectId != YAFFS_OBJECTID_DELETED ) { - yaffs_UpdateObjectHeader(in,NULL, 0, 1); + yaffs_UpdateObjectHeader(in,NULL, 0, 1,0); } @@ -4139,7 +4180,7 @@ int yaffs_FlushFile(yaffs_Object *in, int updateTime) #endif } - retVal = (yaffs_UpdateObjectHeader(in,NULL,0,0) >= 0)? YAFFS_OK : YAFFS_FAIL; + retVal = (yaffs_UpdateObjectHeader(in,NULL,0,0,0) >= 0)? YAFFS_OK : YAFFS_FAIL; } else { @@ -4160,7 +4201,7 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object *in) if(in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) { // Move to the unlinked directory so we have a record that it was deleted. - yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0); + yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0,0); } @@ -4223,7 +4264,7 @@ static int yaffs_UnlinkFile(yaffs_Object *in) #endif if(immediateDeletion) { - retVal = yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0); + retVal = yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0,0); T(YAFFS_TRACE_TRACING,(TSTR("yaffs: immediate deletion of file %d" TENDSTR),in->objectId)); in->deleted=1; in->myDev->nDeletedFiles++; @@ -4235,7 +4276,7 @@ static int yaffs_UnlinkFile(yaffs_Object *in) } else { - retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL,0); + retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL,0,0); } } @@ -4354,7 +4395,7 @@ static int yaffs_UnlinkWorker(yaffs_Object *obj) yaffs_GetObjectName(hl,name,YAFFS_MAX_NAME_LENGTH+1); - retVal = yaffs_ChangeObjectName(obj, hl->parent, name,0); + retVal = yaffs_ChangeObjectName(obj, hl->parent, name,0,0); if(retVal == YAFFS_OK) { @@ -4405,6 +4446,11 @@ int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name) //////////////// Initialisation Scanning ///////////////// +void yaffs_HandleShadowedObject(yaffs_Device *dev, int objId, int backwardScanning) +{ + //Todo +} + #if 0 // For now we use the SmartMedia check. // We look at the blockStatus byte in the first two chunks @@ -4703,6 +4749,11 @@ static int yaffs_Scan(yaffs_Device *dev) in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type); + if(oh->shadowsObject > 0) + { + yaffs_HandleShadowedObject(dev,oh->shadowsObject,0); + } + if(in->valid) { // We have already filled this one. We have a duplicate and need to resolve it. @@ -4907,6 +4958,8 @@ static int yaffs_Scan(yaffs_Device *dev) } + // Handle the unlinked files. Since they were left in an unlinked state we should + // just delete them. { struct list_head *i; struct list_head *n; @@ -4971,10 +5024,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; - if(dev->isYaffs2) - { - blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); - } + blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); // Scan all the blocks to determine their state @@ -5032,7 +5082,6 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) // Sort the blocks // Dungy old bubble sort for now... - if(dev->isYaffs2) { yaffs_BlockIndex temp; int i; @@ -5050,12 +5099,9 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) // Now scan the blocks looking at the data. - if(dev->isYaffs2) - { - startIterator = 0; - endIterator = nBlocksToScan-1; - T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan)); - } + startIterator = 0; + endIterator = nBlocksToScan-1; + T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan)); // For each block.... backwards @@ -5244,7 +5290,8 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) isShrink = 1; } - if(in->variant.fileVariant.shrinkSize > thisSize) + if(isShrink && + in->variant.fileVariant.shrinkSize > thisSize) { in->variant.fileVariant.shrinkSize = thisSize; } @@ -5311,6 +5358,12 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) in->yst_rdev = oh->yst_rdev; #endif in->chunkId = chunk; + + if(oh->shadowsObject > 0) + { + yaffs_HandleShadowedObject(dev,oh->shadowsObject,0); + } + yaffs_SetObjectName(in,oh->name); in->dirty = 0; @@ -5366,15 +5419,13 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) { in->variant.fileVariant.fileSize = oh->fileSize; in->variant.fileVariant.scannedFileSize = in->variant.fileVariant.fileSize; - } + } - - - if(in->variant.fileVariant.shrinkSize > oh->fileSize) + if(oh->isShrink && + in->variant.fileVariant.shrinkSize > oh->fileSize) { in->variant.fileVariant.shrinkSize = oh->fileSize; - } - + } break; case YAFFS_OBJECT_TYPE_HARDLINK: @@ -5547,6 +5598,10 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object *directory,const YCHAR *name) yaffs_Object *l; + if(!name) + { + return NULL; + } if(!directory) { @@ -5777,7 +5832,7 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size); - yaffs_UpdateObjectHeader(obj,NULL,1,0); + yaffs_UpdateObjectHeader(obj,NULL,1,0,0); return YAFFS_OK; @@ -5849,7 +5904,7 @@ int yaffs_DumpObject(yaffs_Object *obj) ///////////////////////// Initialisation code /////////////////////////// -int yaffs_CheckDevFunctions(const yaffs_Device *dev) +static int yaffs_CheckDevFunctions(const yaffs_Device *dev) { // Common functions, gotta have