X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=a16ec55075ef88df2fdd68310cda6534756e532b;hp=6e725ace9d64f3f8f491ee711afc975c42c2a4fb;hb=49942b13d7cfbdba72c18de0f37d16d81b4372a8;hpb=40c386c7a14ebfa8afc14562f3b33a416831b26d diff --git a/yaffs_guts.c b/yaffs_guts.c index 6e725ac..a16ec55 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -12,7 +12,7 @@ */ const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.57 2008-07-02 20:17:41 charles Exp $"; + "$Id: yaffs_guts.c,v 1.62 2008-11-07 00:32:20 charles Exp $"; #include "yportenv.h" @@ -97,6 +97,7 @@ static void yaffs_VerifyFreeChunks(yaffs_Device * dev); static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in); +static void yaffs_VerifyDirectory(yaffs_Object *directory); #ifdef YAFFS_PARANOID static int yaffs_CheckFileSanity(yaffs_Object * in); #else @@ -440,7 +441,7 @@ static void yaffs_VerifyBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) return; /* Report illegal runtime states */ - if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) + if(bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState)); switch(bi->blockState){ @@ -509,7 +510,7 @@ static void yaffs_VerifyBlocks(yaffs_Device *dev) yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); yaffs_VerifyBlock(dev,bi,i); - if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) + if(bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) nBlocksPerState[bi->blockState]++; else nIllegalBlockStates++; @@ -553,7 +554,7 @@ static void yaffs_VerifyBlocks(yaffs_Device *dev) */ static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck) { - if(yaffs_SkipVerification(obj->myDev)) + if(obj && yaffs_SkipVerification(obj->myDev)) return; if(!(tags && obj && oh)){ @@ -628,7 +629,6 @@ static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn, } } } else if (level == 0) { - int i; yaffs_ExtendedTags tags; __u32 objectId = obj->objectId; @@ -668,7 +668,10 @@ static void yaffs_VerifyFile(yaffs_Object *obj) yaffs_Tnode *tn; __u32 objectId; - if(obj && yaffs_SkipVerification(obj->myDev)) + if(!obj) + return; + + if(yaffs_SkipVerification(obj->myDev)) return; dev = obj->myDev; @@ -719,12 +722,6 @@ static void yaffs_VerifyFile(yaffs_Object *obj) } -static void yaffs_VerifyDirectory(yaffs_Object *obj) -{ - if(obj && yaffs_SkipVerification(obj->myDev)) - return; - -} static void yaffs_VerifyHardLink(yaffs_Object *obj) { @@ -767,20 +764,20 @@ static void yaffs_VerifyObject(yaffs_Object *obj) return; /* Check sane object header chunk */ - - chunkMin = dev->internalStartBlock * dev->nChunksPerBlock; - chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1; - - chunkIdOk = (((unsigned)(obj->chunkId)) >= chunkMin && ((unsigned)(obj->chunkId)) <= chunkMax); - chunkIsLive = chunkIdOk && - yaffs_CheckChunkBit(dev, - obj->chunkId / dev->nChunksPerBlock, - obj->chunkId % dev->nChunksPerBlock); - if(!obj->fake && + + chunkMin = dev->internalStartBlock * dev->nChunksPerBlock; + chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1; + + chunkIdOk = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax); + chunkIsLive = chunkIdOk && + yaffs_CheckChunkBit(dev, + obj->hdrChunk / dev->nChunksPerBlock, + obj->hdrChunk % dev->nChunksPerBlock); + if(!obj->fake && (!chunkIdOk || !chunkIsLive)) { T(YAFFS_TRACE_VERIFY, (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), - obj->objectId,obj->chunkId, + obj->objectId,obj->hdrChunk, chunkIdOk ? "" : ",out of range", chunkIsLive || !chunkIdOk ? "" : ",marked as deleted")); } @@ -791,9 +788,9 @@ static void yaffs_VerifyObject(yaffs_Object *obj) __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); oh = (yaffs_ObjectHeader *)buffer; - - yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags); - + + yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags); + yaffs_VerifyObjectHeader(obj,oh,&tags,1); yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); @@ -875,7 +872,8 @@ static Y_INLINE int yaffs_HashFunction(int n) } /* - * Access functions to useful fake objects + * Access functions to useful fake objects. + * Note that root might have a presence in NAND if permissions are set. */ yaffs_Object *yaffs_Root(yaffs_Device * dev) @@ -1105,7 +1103,7 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name) __u16 sum = 0; __u16 i = 1; - YUCHAR *bname = (YUCHAR *) name; + const YUCHAR *bname = (const YUCHAR *) name; if (bname) { while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) { @@ -1118,12 +1116,14 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name) bname++; } } + return sum; } static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name) { #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM + memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) { yaffs_strcpy(obj->shortName, name); } else { @@ -1908,6 +1908,9 @@ 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); @@ -1918,16 +1921,25 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) dev->freeObjects = (yaffs_Object *) (dev->freeObjects->siblings.next); dev->nFreeObjects--; - + } +#endif + if(tn){ /* Now sweeten it up... */ memset(tn, 0, sizeof(yaffs_Object)); - tn->myDev = dev; - tn->chunkId = -1; - tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; - YINIT_LIST_HEAD(&(tn->hardLinks)); - YINIT_LIST_HEAD(&(tn->hashLink)); - YINIT_LIST_HEAD(&tn->siblings); + 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 @@ -1950,14 +1962,14 @@ static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number, 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->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->chunkId = 0; /* Not a valid chunk. */ + obj->hdrChunk = 0; /* Not a valid chunk. */ } return obj; @@ -1984,6 +1996,13 @@ 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. @@ -1996,11 +2015,14 @@ static void yaffs_FreeObject(yaffs_Object * tn) 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*/ } @@ -2198,6 +2220,12 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, theObject->yst_atime = theObject->yst_mtime = theObject->yst_ctime = Y_CURRENT_TIME; #endif + +#if 0 + theObject->sum_prev = 12345; + theObject->sum_trailer = 6789; +#endif + switch (type) { case YAFFS_OBJECT_TYPE_FILE: theObject->variant.fileVariant.fileSize = 0; @@ -2284,6 +2312,9 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, } in = yaffs_CreateNewObject(dev, -1, type); + + if(!in) + return YAFFS_FAIL; if(type == YAFFS_OBJECT_TYPE_SYMLINK){ str = yaffs_CloneString(aliasString); @@ -2296,7 +2327,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, if (in) { - in->chunkId = -1; + in->hdrChunk = 0; in->valid = 1; in->variantType = type; @@ -2414,7 +2445,7 @@ static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir, if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { T(YAFFS_TRACE_ALWAYS, (TSTR - ("tragendy: yaffs_ChangeObjectName: newDir is not a directory" + ("tragedy: yaffs_ChangeObjectName: newDir is not a directory" TENDSTR))); YBUG(); } @@ -2461,9 +2492,15 @@ static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir, int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, yaffs_Object * newDir, const YCHAR * newName) { - yaffs_Object *obj; - yaffs_Object *existingTarget; + yaffs_Object *obj=NULL; + yaffs_Object *existingTarget=NULL; int force = 0; + + + if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); #ifdef CONFIG_YAFFS_CASE_INSENSITIVE /* Special case for case insemsitive systems (eg. WinCE). @@ -2475,17 +2512,12 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, } #endif - obj = yaffs_FindObjectByName(oldDir, oldName); - /* Check new name to long. */ - if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK && - yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH) - /* ENAMETOOLONG */ - return YAFFS_FAIL; - else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK && - yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) + else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) /* ENAMETOOLONG */ return YAFFS_FAIL; + obj = yaffs_FindObjectByName(oldDir, oldName); + if (obj && obj->renameAllowed) { /* Now do the handling for an existing target, if there is one */ @@ -2799,7 +2831,7 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev) * Can't get space to gc */ T(YAFFS_TRACE_ERROR, - (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR))); + (TSTR("yaffs tragedy: no more erased blocks" TENDSTR))); return -1; } @@ -2830,7 +2862,7 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev) T(YAFFS_TRACE_ALWAYS, (TSTR - ("yaffs tragedy: no more eraased blocks, but there should have been %d" + ("yaffs tragedy: no more erased blocks, but there should have been %d" TENDSTR), dev->nErasedBlocks)); return -1; @@ -2840,7 +2872,8 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev) static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev) { - if(!dev->nCheckpointBlocksRequired){ + if(!dev->nCheckpointBlocksRequired && + dev->isYaffs2){ /* Not a valid value so recalculate */ int nBytes = 0; int nBlocks; @@ -2879,9 +2912,14 @@ static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev) int reservedBlocks = dev->nReservedBlocks; int checkpointBlocks; - checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; - if(checkpointBlocks < 0) - checkpointBlocks = 0; + if(dev->isYaffs2){ + checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) - + dev->blocksInCheckpoint; + if(checkpointBlocks < 0) + checkpointBlocks = 0; + } else { + checkpointBlocks =0; + } reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock); @@ -3009,6 +3047,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) yaffs_VerifyBlock(dev,bi,block); for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock; + retVal == YAFFS_OK && chunkInBlock < dev->nChunksPerBlock && yaffs_StillSomeChunkBits(dev, block); chunkInBlock++, oldChunk++) { @@ -3035,7 +3074,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) if(object && !yaffs_SkipVerification(dev)){ if(tags.chunkId == 0) - matchingChunk = object->chunkId; + matchingChunk = object->hdrChunk; else if(object->softDeleted) matchingChunk = oldChunk; /* Defeat the test */ else @@ -3056,9 +3095,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) tags.objectId, tags.chunkId, tags.byteCount)); } - if (object && object->deleted - && tags.chunkId != 0) { - /* Data chunk in a deleted file, throw it away + if (object && + object->deleted && + object->softDeleted && + tags.chunkId != 0) { + /* Data chunk in a soft deleted file, throw it away * It's a soft deleted data chunk, * No need to copy this, just forget about it and * fix up the object. @@ -3079,7 +3120,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) /* Deleted object header with no data chunks. * Can be discarded and the file deleted. */ - object->chunkId = 0; + object->hdrChunk = 0; yaffs_FreeTnode(object->myDev, object->variant. fileVariant.top); @@ -3125,7 +3166,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) if (tags.chunkId == 0) { /* It's a header */ - object->chunkId = newChunk; + object->hdrChunk = newChunk; object->serial = tags.serialNumber; } else { /* It's a data chunk */ @@ -3137,7 +3178,8 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) } } - yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__); + if(retVal == YAFFS_OK) + yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__); } } @@ -3179,7 +3221,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) dev->isDoingGC = 0; - return YAFFS_OK; + return retVal; } /* New garbage collector @@ -3444,7 +3486,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, * Update: For backward scanning we don't need to re-read tags so this is quite cheap. */ - if (existingChunk != 0) { + if (existingChunk > 0) { /* NB Right now existing chunk will not be real chunkId if the device >= 32MB * thus we have to do a FindChunkInFile to get the real chunk id. * @@ -3481,8 +3523,10 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, * not be loaded during a scan */ - newSerial = newTags.serialNumber; - existingSerial = existingTags.serialNumber; + if(inScan > 0) { + newSerial = newTags.serialNumber; + existingSerial = existingTags.serialNumber; + } if ((inScan > 0) && (in->myDev->isYaffs2 || @@ -3630,6 +3674,14 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode, newTags.serialNumber = (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1; newTags.byteCount = nBytes; + + if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){ + T(YAFFS_TRACE_ERROR, + (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); + while(1){} + } + + newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, @@ -3675,7 +3727,10 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, yaffs_strcpy(oldName,_Y("silly old name")); - if (!in->fake || force) { + + if (!in->fake || + in == dev->rootDir || /* The rootDir should also be saved */ + force) { yaffs_CheckGarbageCollection(dev); yaffs_CheckObjectDetailsLoaded(in); @@ -3683,9 +3738,9 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, buffer = yaffs_GetTempBuffer(in->myDev, __LINE__); oh = (yaffs_ObjectHeader *) buffer; - prevChunkId = in->chunkId; + prevChunkId = in->hdrChunk; - if (prevChunkId >= 0) { + if (prevChunkId > 0) { result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId, buffer, &oldTags); @@ -3787,7 +3842,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, if (newChunkId >= 0) { - in->chunkId = newChunkId; + in->hdrChunk = newChunkId; if (prevChunkId >= 0) { yaffs_DeleteChunk(dev, prevChunkId, 1, @@ -3936,35 +3991,15 @@ void yaffs_FlushEntireDeviceCache(yaffs_Device *dev) static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev) { int i; - int usage; - int theOne; if (dev->nShortOpCaches > 0) { for (i = 0; i < dev->nShortOpCaches; i++) { if (!dev->srCache[i].object) return &dev->srCache[i]; } - - return NULL; - - theOne = -1; - usage = 0; /* just to stop the compiler grizzling */ - - for (i = 0; i < dev->nShortOpCaches; i++) { - if (!dev->srCache[i].dirty && - ((dev->srCache[i].lastUse < usage && theOne >= 0) || - theOne < 0)) { - usage = dev->srCache[i].lastUse; - theOne = i; - } - } - - - return theOne >= 0 ? &dev->srCache[theOne] : NULL; - } else { - return NULL; } + return NULL; } static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev) @@ -4227,8 +4262,8 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, cp->objectId = obj->objectId; cp->parentId = (obj->parent) ? obj->parent->objectId : 0; - cp->chunkId = obj->chunkId; - cp->variantType = obj->variantType; + cp->hdrChunk = obj->hdrChunk; + cp->variantType = obj->variantType; cp->deleted = obj->deleted; cp->softDeleted = obj->softDeleted; cp->unlinked = obj->unlinked; @@ -4261,9 +4296,9 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb if(parent) yaffs_AddObjectToDirectory(parent, obj); - - obj->chunkId = cp->chunkId; - obj->variantType = cp->variantType; + + obj->hdrChunk = cp->hdrChunk; + obj->variantType = cp->variantType; obj->deleted = cp->deleted; obj->softDeleted = cp->softDeleted; obj->unlinked = cp->unlinked; @@ -4277,8 +4312,8 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId; else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId; - - if(obj->objectId >= YAFFS_NOBJECT_BUCKETS) + + if(obj->hdrChunk > 0) obj->lazyLoaded = 1; } @@ -4409,8 +4444,8 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) T(YAFFS_TRACE_CHECKPOINT,( TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR), - cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); - + cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk,(unsigned) obj)); + ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){ @@ -4448,8 +4483,8 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) } T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR), - cp.objectId,cp.parentId,cp.variantType,cp.chunkId)); - + cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk)); + if(ok && cp.objectId == ~0) done = 1; else if(ok){ @@ -4803,6 +4838,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, //chunk = offset / dev->nDataBytesPerChunk + 1; //start = offset % dev->nDataBytesPerChunk; yaffs_AddrToChunk(dev,offset,&chunk,&start); + + if(chunk * dev->nDataBytesPerChunk + start != offset || + start >= dev->nDataBytesPerChunk){ + T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR), + (int)offset, chunk,start)); + } chunk++; /* OK now check for the curveball where the start and end are in @@ -5079,7 +5120,8 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize) * show we've shrunk the file, if need be * Do this only if the file is not in the deleted directories. */ - if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED && + if (in->parent && + in->parent->objectId != YAFFS_OBJECTID_UNLINKED && in->parent->objectId != YAFFS_OBJECTID_DELETED) { yaffs_UpdateObjectHeader(in, NULL, 0, (newSize < oldFileSize) ? 1 : 0, 0); @@ -5143,8 +5185,8 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) } yaffs_RemoveObjectFromDirectory(in); - yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__); - in->chunkId = -1; + yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__); + in->hdrChunk = 0; yaffs_FreeObject(in); return YAFFS_OK; @@ -5155,62 +5197,66 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) * and the inode associated with the file. * It does not delete the links associated with the file. */ + static int yaffs_UnlinkFile(yaffs_Object * in) { int retVal; int immediateDeletion = 0; - if (1) { #ifdef __KERNEL__ - if (!in->myInode) { - immediateDeletion = 1; - - } + if (!in->myInode) { + immediateDeletion = 1; + } #else - if (in->inUse <= 0) { - immediateDeletion = 1; - - } + if (in->inUse <= 0) { + immediateDeletion = 1; + } #endif - if (immediateDeletion) { - retVal = - yaffs_ChangeObjectName(in, in->myDev->deletedDir, - _Y("deleted"), 0, 0); - T(YAFFS_TRACE_TRACING, - (TSTR("yaffs: immediate deletion of file %d" TENDSTR), - in->objectId)); - in->deleted = 1; - in->myDev->nDeletedFiles++; - if (0 && in->myDev->isYaffs2) { - yaffs_ResizeFile(in, 0); - } - yaffs_SoftDeleteFile(in); - } else { - retVal = - yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, - _Y("unlinked"), 0, 0); - } + if (immediateDeletion) { + retVal = + yaffs_ChangeObjectName(in, in->myDev->deletedDir, + _Y("deleted"), 0, 0); + T(YAFFS_TRACE_TRACING, + (TSTR("yaffs: immediate deletion of file %d" TENDSTR), + in->objectId)); + in->deleted = 1; + in->myDev->nDeletedFiles++; + if (1 || in->myDev->isYaffs2) { + yaffs_ResizeFile(in, 0); + } + yaffs_SoftDeleteFile(in); + } else { + retVal = + yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, + _Y("unlinked"), 0, 0); } + + return retVal; } int yaffs_DeleteFile(yaffs_Object * in) { int retVal = YAFFS_OK; + int deleted = in->deleted; + + yaffs_ResizeFile(in,0); if (in->nDataChunks > 0) { - /* Use soft deletion if there is data in the file */ + /* Use soft deletion if there is data in the file. + * That won't be the case if it has been resized to zero. + */ if (!in->unlinked) { retVal = yaffs_UnlinkFile(in); } if (retVal == YAFFS_OK && in->unlinked && !in->deleted) { - in->deleted = 1; + in->deleted = deleted = 1; in->myDev->nDeletedFiles++; yaffs_SoftDeleteFile(in); } - return in->deleted ? YAFFS_OK : YAFFS_FAIL; + return deleted ? YAFFS_OK : YAFFS_FAIL; } else { /* The file has no data chunks so we toss it immediately */ yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top); @@ -5244,7 +5290,7 @@ static int yaffs_DeleteHardLink(yaffs_Object * in) /* remove this hardlink from the list assocaited with the equivalent * object */ - ylist_del(&in->hardLinks); + ylist_del_init(&in->hardLinks); return yaffs_DoGenericObjectDeletion(in); } @@ -5470,7 +5516,6 @@ static int yaffs_Scan(yaffs_Device * dev) __u8 *chunkData; - //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format. T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR), @@ -5536,7 +5581,7 @@ static int yaffs_Scan(yaffs_Device * dev) /* Let's have a good look at this chunk... */ - if (!dev->isYaffs2 && tags.chunkDeleted) { + if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) { /* YAFFS1 only... * A deleted chunk */ @@ -5565,17 +5610,6 @@ static int yaffs_Scan(yaffs_Device * dev) dev->allocationBlockFinder = blk; /* Set it to here to encourage the allocator to go forth from here. */ - /* Yaffs2 sanity check: - * This should be the one with the highest sequence number - */ - if (dev->isYaffs2 - && (dev->sequenceNumber != - bi->sequenceNumber)) { - T(YAFFS_TRACE_ALWAYS, - (TSTR - ("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" - TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber)); - } } dev->nFreeChunks += (dev->nChunksPerBlock - c); @@ -5673,12 +5707,10 @@ static int yaffs_Scan(yaffs_Device * dev) unsigned existingSerial = in->serial; unsigned newSerial = tags.serialNumber; - if (dev->isYaffs2 || - ((existingSerial + 1) & 3) == - newSerial) { + if (((existingSerial + 1) & 3) == newSerial) { /* Use new one - destroy the exisiting one */ yaffs_DeleteChunk(dev, - in->chunkId, + in->hdrChunk, 1, __LINE__); in->valid = 0; } else { @@ -5711,7 +5743,7 @@ static int yaffs_Scan(yaffs_Device * dev) in->yst_ctime = oh->yst_ctime; in->yst_rdev = oh->yst_rdev; #endif - in->chunkId = chunk; + in->hdrChunk = chunk; } else if (in && !in->valid) { /* we need to load this info */ @@ -5735,7 +5767,7 @@ static int yaffs_Scan(yaffs_Device * dev) in->yst_ctime = oh->yst_ctime; in->yst_rdev = oh->yst_rdev; #endif - in->chunkId = chunk; + in->hdrChunk = chunk; yaffs_SetObjectName(in, oh->name); in->dirty = 0; @@ -5789,15 +5821,6 @@ static int yaffs_Scan(yaffs_Device * dev) /* Todo got a problem */ break; case YAFFS_OBJECT_TYPE_FILE: - if (dev->isYaffs2 - && oh->isShrink) { - /* Prune back the shrunken chunks */ - yaffs_PruneResizedChunks - (in, oh->fileSize); - /* Mark the block as having a shrinkHeader */ - bi->hasShrinkHeader = 1; - } - if (dev->useHeaderFileSize) in->variant.fileVariant. @@ -5828,10 +5851,12 @@ static int yaffs_Scan(yaffs_Device * dev) break; } - if (parent == dev->deletedDir) { +/* + if (parent == dev->deletedDir) { yaffs_DestroyObject(in); bi->hasShrinkHeader = 1; } +*/ } } } @@ -5920,7 +5945,7 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) { __u8 *chunkData; yaffs_ObjectHeader *oh; - yaffs_Device *dev = in->myDev; + yaffs_Device *dev; yaffs_ExtendedTags tags; int result; int alloc_failed = 0; @@ -5928,18 +5953,20 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) if(!in) return; + dev = in->myDev; + #if 0 T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR), in->objectId, in->lazyLoaded ? "not yet" : "already")); #endif - if(in->lazyLoaded){ + if(in->lazyLoaded && in->hdrChunk > 0){ in->lazyLoaded = 0; chunkData = yaffs_GetTempBuffer(dev, __LINE__); - result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags); - oh = (yaffs_ObjectHeader *) chunkData; + result = yaffs_ReadChunkWithTagsFromNAND(dev,in->hdrChunk,chunkData,&tags); + oh = (yaffs_ObjectHeader *) chunkData; in->yst_mode = oh->yst_mode; #ifdef CONFIG_YAFFS_WINCE @@ -6070,8 +6097,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { /* Determine the highest sequence number */ - if (dev->isYaffs2 && - sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && + if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) { blockIndex[nBlocksToScan].seq = sequenceNumber; @@ -6082,7 +6108,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) if (sequenceNumber >= dev->sequenceNumber) { dev->sequenceNumber = sequenceNumber; } - } else if (dev->isYaffs2) { + } else { /* TODO: Nasty sequence number! */ T(YAFFS_TRACE_SCAN, (TSTR @@ -6208,11 +6234,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) * had a write failure, so set up for retirement. */ - bi->needsRetiring = 1; + /* bi->needsRetiring = 1; ??? TODO */ bi->gcPrioritise = 1; T(YAFFS_TRACE_ALWAYS, - (TSTR("Partially written block %d being set for retirement" TENDSTR), + (TSTR("Partially written block %d detected" TENDSTR), blk)); } @@ -6356,7 +6382,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) (oh) ? oh-> parentObjectId : tags. extraParentObjectId; - unsigned isShrink = + + + isShrink = (oh) ? oh->isShrink : tags. extraIsShrinkHeader; @@ -6420,15 +6448,15 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) in->variantType = tags.extraObjectType; in->lazyLoaded = 1; } - - in->chunkId = chunk; + + in->hdrChunk = chunk; } else if (!in->valid) { /* we need to load this info */ in->valid = 1; - in->chunkId = chunk; - + in->hdrChunk = chunk; + if(oh) { in->variantType = oh->type; @@ -6653,15 +6681,91 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) /*------------------------------ Directory Functions ----------------------------- */ +static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) +{ + struct ylist_head *lh; + yaffs_Object *listObj; + + int count = 0; + + if(!obj) + YBUG(); + + if(yaffs_SkipVerification(obj->myDev)) + return; + + if(!obj->parent) + YBUG(); + + if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + + /* Iterate through the objects in each hash entry */ + + ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) { + if (lh) { + listObj = ylist_entry(lh, yaffs_Object, siblings); + yaffs_VerifyObject(listObj); + if(obj == listObj) + count ++; + } + } + + if(count != 1) + YBUG(); + + +} + +static void yaffs_VerifyDirectory(yaffs_Object *directory) +{ + + struct ylist_head *lh; + yaffs_Object *listObj; + + if(!directory) + YBUG(); + + if(yaffs_SkipVerification(directory->myDev)) + return; + + + if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + YBUG(); + + /* Iterate through the objects in each hash entry */ + + ylist_for_each(lh, &directory->variant.directoryVariant.children) { + if (lh) { + listObj = ylist_entry(lh, yaffs_Object, siblings); + if(listObj->parent != directory) + YBUG(); + yaffs_VerifyObjectInDirectory(listObj); + } + } + +} + + static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) { yaffs_Device *dev = obj->myDev; + yaffs_Object *parent; + + yaffs_VerifyObjectInDirectory(obj); + parent = obj->parent; + yaffs_VerifyDirectory(parent); + if(dev && dev->removeObjectCallback) dev->removeObjectCallback(obj); + ylist_del_init(&obj->siblings); obj->parent = NULL; + + yaffs_VerifyDirectory(parent); + } @@ -6686,12 +6790,18 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, if (obj->siblings.prev == NULL) { /* Not initialised */ - YINIT_LIST_HEAD(&obj->siblings); + YBUG(); - } else if (!ylist_empty(&obj->siblings)) { - /* If it is holed up somewhere else, un hook it */ - yaffs_RemoveObjectFromDirectory(obj); - } + } else if (ylist_empty(&obj->siblings)) { + YBUG(); + } + + + yaffs_VerifyDirectory(directory); + + yaffs_RemoveObjectFromDirectory(obj); + + /* Now add it */ ylist_add(&obj->siblings, &directory->variant.directoryVariant.children); obj->parent = directory; @@ -6702,6 +6812,11 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, obj->myDev->nUnlinkedFiles++; obj->renameAllowed = 0; } + + yaffs_VerifyDirectory(directory); + yaffs_VerifyObjectInDirectory(obj); + + } yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, @@ -6738,6 +6853,9 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, if (i) { l = ylist_entry(i, yaffs_Object, siblings); + if(l->parent != directory) + YBUG(); + yaffs_CheckObjectDetailsLoaded(l); /* Special case for lost-n-found */ @@ -6745,9 +6863,8 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) { return l; } - } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) - { - /* LostnFound cunk called Objxxx + } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0){ + /* LostnFound chunk called Objxxx * Do a real check */ yaffs_GetObjectName(l, buffer, @@ -6822,7 +6939,7 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); - } else if (obj->chunkId <= 0) { + } else if (obj->hdrChunk <= 0) { YCHAR locName[20]; /* make up a name */ yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX, @@ -6843,9 +6960,9 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) memset(buffer, 0, obj->myDev->nDataBytesPerChunk); - if (obj->chunkId >= 0) { + if (obj->hdrChunk > 0) { result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev, - obj->chunkId, buffer, + obj->hdrChunk, buffer, NULL); } yaffs_strncpy(name, oh->name, buffSize - 1); @@ -7006,7 +7123,7 @@ int yaffs_DumpObject(yaffs_Object * obj) ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d" " chunk %d type %d size %d\n" TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name, - obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId, + obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk, yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj))); return YAFFS_OK; @@ -7105,7 +7222,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) /* Check geometry parameters. */ if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || - (!dev->isYaffs2 && dev->totalBytesPerChunk != 512) || + (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || (dev->inbandTags && !dev->isYaffs2 ) || dev->nChunksPerBlock < 2 || dev->nReservedBlocks < 2 || @@ -7159,24 +7276,19 @@ int yaffs_GutsInitialise(yaffs_Device * dev) dev->isMounted = 1; - - /* OK now calculate a few things for the device */ /* * Calculate all the chunk size manipulation numbers: */ - { - __u32 x = dev->nDataBytesPerChunk; - /* We always use dev->chunkShift and dev->chunkDiv */ - dev->chunkShift = Shifts(x); - x >>= dev->chunkShift; - dev->chunkDiv = x; - /* We only use chunk mask if chunkDiv is 1 */ - dev->chunkMask = (1<chunkShift) - 1; - } + x = dev->nDataBytesPerChunk; + /* We always use dev->chunkShift and dev->chunkDiv */ + dev->chunkShift = Shifts(x); + x >>= dev->chunkShift; + dev->chunkDiv = x; + /* We only use chunk mask if chunkDiv is 1 */ + dev->chunkMask = (1<chunkShift) - 1; - /* * Calculate chunkGroupBits. * We need to find the next power of 2 > than internalEndBlock @@ -7264,7 +7376,9 @@ int yaffs_GutsInitialise(yaffs_Device * dev) dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES; } - buf = dev->srCache = YMALLOC(srCacheBytes); + dev->srCache = YMALLOC(srCacheBytes); + + buf = (__u8 *) dev->srCache; if(dev->srCache) memset(dev->srCache,0,srCacheBytes); @@ -7306,6 +7420,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev) /* Now scan the flash. */ if (dev->isYaffs2) { if(yaffs_CheckpointRestore(dev)) { + yaffs_CheckObjectDetailsLoaded(dev->rootDir); T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: restored from checkpoint" TENDSTR))); } else { @@ -7401,6 +7516,9 @@ void yaffs_Deinitialise(yaffs_Device * dev) dev->isMounted = 0; + + if(dev->deinitialiseNAND) + dev->deinitialiseNAND(dev); } }