X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=6d199656b38052f25e7f048e810bb4cdd4c3d747;hp=d4ecda3c035e74375bf4db24e147ed495b4fa882;hb=a89cf765098ba9927eafeaca0f303eb76052fc64;hpb=92ee023b9d7144e178a050eff898aaae4415096b diff --git a/yaffs_guts.c b/yaffs_guts.c index d4ecda3..6d19965 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.58 2008-07-03 20:06:05 charles Exp $"; + "$Id: yaffs_guts.c,v 1.64 2008-11-25 00:29:32 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) { @@ -1106,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))) { @@ -1119,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 { @@ -1909,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); @@ -1919,7 +1921,9 @@ 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)); @@ -1929,6 +1933,13 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) 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 @@ -1985,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. @@ -1997,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*/ } @@ -2199,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; @@ -2285,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); @@ -2415,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(); } @@ -2462,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). @@ -2476,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 */ @@ -2800,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; } @@ -2831,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; @@ -2841,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; @@ -2880,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); @@ -3010,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++) { @@ -3057,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. @@ -3138,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__); } } @@ -3180,7 +3221,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) dev->isDoingGC = 0; - return YAFFS_OK; + return retVal; } /* New garbage collector @@ -3482,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 || @@ -3631,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, @@ -3940,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) @@ -4807,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 @@ -4831,7 +4868,7 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, nToWriteBack = (nBytesRead > - (start + n)) ? nBytesRead : (start + n); + ((int)start + n)) ? nBytesRead : (start + n); } else { nToCopy = dev->nDataBytesPerChunk - start; @@ -5083,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); @@ -5159,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); @@ -5248,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); } @@ -5474,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), @@ -5540,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 */ @@ -5569,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); @@ -5677,9 +5707,7 @@ 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->hdrChunk, @@ -5716,6 +5744,7 @@ static int yaffs_Scan(yaffs_Device * dev) in->yst_rdev = oh->yst_rdev; #endif in->hdrChunk = chunk; + in->serial = tags.serialNumber; } else if (in && !in->valid) { /* we need to load this info */ @@ -5740,6 +5769,7 @@ static int yaffs_Scan(yaffs_Device * dev) in->yst_rdev = oh->yst_rdev; #endif in->hdrChunk = chunk; + in->serial = tags.serialNumber; yaffs_SetObjectName(in, oh->name); in->dirty = 0; @@ -5793,15 +5823,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. @@ -5832,10 +5853,12 @@ static int yaffs_Scan(yaffs_Device * dev) break; } - if (parent == dev->deletedDir) { +/* + if (parent == dev->deletedDir) { yaffs_DestroyObject(in); bi->hasShrinkHeader = 1; } +*/ } } } @@ -5924,7 +5947,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; @@ -5932,6 +5955,8 @@ 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, @@ -6074,8 +6099,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; @@ -6086,7 +6110,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 @@ -6212,11 +6236,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)); } @@ -6360,7 +6384,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) (oh) ? oh-> parentObjectId : tags. extraParentObjectId; - unsigned isShrink = + + + isShrink = (oh) ? oh->isShrink : tags. extraIsShrinkHeader; @@ -6657,15 +6683,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); + } @@ -6690,12 +6792,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; @@ -6706,6 +6814,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, @@ -6742,6 +6855,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 */ @@ -7108,7 +7224,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 || @@ -7162,24 +7278,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 @@ -7267,7 +7378,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); @@ -7405,6 +7518,9 @@ void yaffs_Deinitialise(yaffs_Device * dev) dev->isMounted = 0; + + if(dev->deinitialiseNAND) + dev->deinitialiseNAND(dev); } }