X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=a09328e95b42ee1b70d34388841819a79d606245;hp=72532c2b6a9627f1231c7bfc33f0423c8f3453e3;hb=18fcce7fefa7e3d67ac8a7455056395567564617;hpb=f8021b6b5a5f5d9b407c9be95f96da6999cdc247 diff --git a/yaffs_guts.c b/yaffs_guts.c index 72532c2..a09328e 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.68 2008-11-27 20:32:52 charles Exp $"; + "$Id: yaffs_guts.c,v 1.79 2009-03-05 01:45:28 charles Exp $"; #include "yportenv.h" @@ -33,11 +33,6 @@ const char *yaffs_guts_c_version = #include "yaffs_packedtags2.h" -#ifdef CONFIG_YAFFS_WINCE -void yfsd_LockYAFFS(BOOL fsLockOnly); -void yfsd_UnlockYAFFS(BOOL fsLockOnly); -#endif - #define YAFFS_PASSIVE_GC_CHUNKS 2 #include "yaffs_ecc.h" @@ -84,7 +79,6 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, int chunkInNAND); static int yaffs_UnlinkWorker(yaffs_Object * obj); -static void yaffs_DestroyObject(yaffs_Object * obj); static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, int chunkInObject); @@ -482,9 +476,10 @@ static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int yaffs_VerifyBlock(dev,bi,n); /* After collection the block should be in the erased state */ - /* TODO: This will need to change if we do partial gc */ + /* This will need to change if we do partial gc */ - if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){ + if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && + bi->blockState != YAFFS_BLOCK_STATE_EMPTY){ T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), n,bi->blockState)); } @@ -750,10 +745,15 @@ static void yaffs_VerifyObject(yaffs_Object *obj) __u32 chunkMax; __u32 chunkIdOk; - __u32 chunkIsLive; + __u32 chunkInRange; + __u32 chunkShouldNotBeDeleted; + __u32 chunkValid; if(!obj) return; + + if(obj->beingCreated) + return; dev = obj->myDev; @@ -765,21 +765,24 @@ static void yaffs_VerifyObject(yaffs_Object *obj) chunkMin = dev->internalStartBlock * dev->nChunksPerBlock; chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1; - chunkIdOk = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax); - chunkIsLive = chunkIdOk && + chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax); + chunkIdOk = chunkInRange || obj->hdrChunk == 0; + chunkValid = chunkInRange && yaffs_CheckChunkBit(dev, obj->hdrChunk / dev->nChunksPerBlock, obj->hdrChunk % dev->nChunksPerBlock); + chunkShouldNotBeDeleted = chunkInRange && !chunkValid; + if(!obj->fake && - (!chunkIdOk || !chunkIsLive)) { + (!chunkIdOk || chunkShouldNotBeDeleted)) { T(YAFFS_TRACE_VERIFY, (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), obj->objectId,obj->hdrChunk, chunkIdOk ? "" : ",out of range", - chunkIsLive || !chunkIdOk ? "" : ",marked as deleted")); + chunkShouldNotBeDeleted ? ",marked as deleted" : "")); } - if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) { + if(chunkValid &&!yaffs_SkipNANDVerification(dev)) { yaffs_ExtendedTags tags; yaffs_ObjectHeader *oh; __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); @@ -1029,7 +1032,30 @@ static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND) yaffs_InvalidateCheckpoint(dev); - yaffs_MarkBlockBad(dev, blockInNAND); + if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) { + if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) { + T(YAFFS_TRACE_ALWAYS, (TSTR( + "yaffs: Failed to mark bad and erase block %d" + TENDSTR), blockInNAND)); + } + else { + yaffs_ExtendedTags tags; + int chunkId = blockInNAND * dev->nChunksPerBlock; + + __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); + + memset(buffer, 0xff, dev->nDataBytesPerChunk); + yaffs_InitialiseTags(&tags); + tags.sequenceNumber = YAFFS_SEQUENCE_BAD_BLOCK; + if (dev->writeChunkWithTagsToNAND(dev, chunkId - + dev->chunkOffset, buffer, &tags) != YAFFS_OK) + T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Failed to " + TCONT("write bad block marker to block %d") + TENDSTR), blockInNAND)); + + yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); + } + } bi->blockState = YAFFS_BLOCK_STATE_DEAD; bi->gcPrioritise = 0; @@ -1113,7 +1139,6 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name) bname++; } } - return sum; } @@ -1924,6 +1949,8 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) /* 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; @@ -1945,6 +1972,8 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) if (dev->lostNFoundDir) { yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn); } + + tn->beingCreated = 0; } dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ @@ -1993,6 +2022,9 @@ static void yaffs_FreeObject(yaffs_Object * tn) yaffs_Device *dev = tn->myDev; +#ifdef __KERNEL__ + T(YAFFS_TRACE_OS,(TSTR("FreeObject %p inode %p"TENDSTR),tn,tn->myInode)); +#endif if(tn->parent) YBUG(); @@ -2217,12 +2249,6 @@ 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; @@ -2372,7 +2398,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) { /* Could not create the object header, fail the creation */ - yaffs_DestroyObject(in); + yaffs_DeleteObject(in); in = NULL; } @@ -3148,13 +3174,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlo * 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. - * Also, clear out any shadowing stuff */ yaffs_ObjectHeader *oh; oh = (yaffs_ObjectHeader *)buffer; oh->isShrink = 0; - tags.extraShadows = 0; tags.extraIsShrinkHeader = 0; yaffs_VerifyObjectHeader(object,oh,&tags,1); @@ -3190,7 +3214,6 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlo } yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); - /* Do any required cleanups */ @@ -3696,8 +3719,8 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode, if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){ T(YAFFS_TRACE_ERROR, (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); - while(1){} - } + YBUG(); + } @@ -4297,10 +4320,18 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp, cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId; } -static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp) +static int yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp) { yaffs_Object *parent; + + if (obj->variantType != cp->variantType) { + T(YAFFS_TRACE_ERROR,(TSTR("Checkpoint read object %d type %d " + TCONT("chunk %d does not match existing object type %d") + TENDSTR), cp->objectId, cp->variantType, cp->hdrChunk, + obj->variantType)); + return 0; + } obj->objectId = cp->objectId; @@ -4312,8 +4343,16 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb else parent = NULL; - if(parent) + if(parent) { + if (parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { + T(YAFFS_TRACE_ALWAYS,(TSTR("Checkpoint read object %d parent %d type %d" + TCONT(" chunk %d Parent type, %d, not directory") + TENDSTR), + cp->objectId,cp->parentId,cp->variantType,cp->hdrChunk,parent->variantType)); + return 0; + } yaffs_AddObjectToDirectory(parent, obj); + } obj->hdrChunk = cp->hdrChunk; obj->variantType = cp->variantType; @@ -4333,6 +4372,7 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb if(obj->hdrChunk > 0) obj->lazyLoaded = 1; + return 1; } @@ -4362,7 +4402,6 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn, } } else if (level == 0) { __u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS; - /* printf("write tnode at %d\n",baseOffset); */ ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset)); if(ok) ok = (yaffs_CheckpointWrite(dev,tn,tnodeSize) == tnodeSize); @@ -4411,7 +4450,6 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj) /* Read level 0 tnode */ - /* printf("read tnode at %d\n",baseChunk); */ tn = yaffs_GetTnodeRaw(dev); if(tn) ok = (yaffs_CheckpointRead(dev,tn,tnodeSize) == tnodeSize); @@ -4508,7 +4546,9 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) else if(ok){ obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); if(obj) { - yaffs_CheckpointObjectToObject(obj,&cp); + ok = yaffs_CheckpointObjectToObject(obj,&cp); + if (!ok) + break; if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { ok = yaffs_ReadCheckpointTnodes(obj); } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { @@ -4519,6 +4559,8 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) } } + else + ok = 0; } } @@ -4771,14 +4813,9 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, cache->locked = 1; -#ifdef CONFIG_YAFFS_WINCE - yfsd_UnlockYAFFS(TRUE); -#endif + memcpy(buffer, &cache->data[start], nToCopy); -#ifdef CONFIG_YAFFS_WINCE - yfsd_LockYAFFS(TRUE); -#endif cache->locked = 0; } else { /* Read into the local buffer then copy..*/ @@ -4787,41 +4824,19 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, yaffs_GetTempBuffer(dev, __LINE__); yaffs_ReadChunkDataFromObject(in, chunk, localBuffer); -#ifdef CONFIG_YAFFS_WINCE - yfsd_UnlockYAFFS(TRUE); -#endif + memcpy(buffer, &localBuffer[start], nToCopy); -#ifdef CONFIG_YAFFS_WINCE - yfsd_LockYAFFS(TRUE); -#endif + yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); } } else { -#ifdef CONFIG_YAFFS_WINCE - __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); - - /* Under WinCE can't do direct transfer. Need to use a local buffer. - * This is because we otherwise screw up WinCE's memory mapper - */ - yaffs_ReadChunkDataFromObject(in, chunk, localBuffer); -#ifdef CONFIG_YAFFS_WINCE - yfsd_UnlockYAFFS(TRUE); -#endif - memcpy(buffer, localBuffer, dev->nDataBytesPerChunk); - -#ifdef CONFIG_YAFFS_WINCE - yfsd_LockYAFFS(TRUE); - yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); -#endif - -#else /* A full chunk. Read directly into the supplied buffer. */ yaffs_ReadChunkDataFromObject(in, chunk, buffer); -#endif + } n -= nToCopy; @@ -4846,7 +4861,8 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, int nToWriteBack; int startOfWrite = offset; int chunkWritten = 0; - int nBytesRead; + __u32 nBytesRead; + __u32 chunkStart; yaffs_Device *dev; @@ -4859,8 +4875,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, 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)); + T(YAFFS_TRACE_ERROR,( + TSTR("AddrToChunk of offset %d gives chunk %d start %d" + TENDSTR), + (int)offset, chunk,start)); } chunk++; @@ -4876,9 +4894,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, * we need to write back as much as was there before. */ - nBytesRead = - in->variant.fileVariant.fileSize - - ((chunk - 1) * dev->nDataBytesPerChunk); + chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk); + + if(chunkStart > in->variant.fileVariant.fileSize) + nBytesRead = 0; /* Past end of file */ + else + nBytesRead = in->variant.fileVariant.fileSize - chunkStart; if (nBytesRead > dev->nDataBytesPerChunk) { nBytesRead = dev->nDataBytesPerChunk; @@ -4886,7 +4907,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, nToWriteBack = (nBytesRead > - ((int)start + n)) ? nBytesRead : (start + n); + (start + n)) ? nBytesRead : (start + n); + + if(nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk) + YBUG(); } else { nToCopy = dev->nDataBytesPerChunk - start; @@ -4926,16 +4950,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, if (cache) { yaffs_UseChunkCache(dev, cache, 1); cache->locked = 1; -#ifdef CONFIG_YAFFS_WINCE - yfsd_UnlockYAFFS(TRUE); -#endif + memcpy(&cache->data[start], buffer, nToCopy); -#ifdef CONFIG_YAFFS_WINCE - yfsd_LockYAFFS(TRUE); -#endif + cache->locked = 0; cache->nBytes = nToWriteBack; @@ -4963,15 +4983,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, yaffs_ReadChunkDataFromObject(in, chunk, localBuffer); -#ifdef CONFIG_YAFFS_WINCE - yfsd_UnlockYAFFS(TRUE); -#endif + memcpy(&localBuffer[start], buffer, nToCopy); -#ifdef CONFIG_YAFFS_WINCE - yfsd_LockYAFFS(TRUE); -#endif chunkWritten = yaffs_WriteChunkDataToObject(in, chunk, localBuffer, @@ -4986,30 +5001,13 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, } else { /* A full chunk. Write directly from the supplied buffer. */ -#ifdef CONFIG_YAFFS_WINCE - /* Under WinCE can't do direct transfer. Need to use a local buffer. - * This is because we otherwise screw up WinCE's memory mapper - */ - __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); -#ifdef CONFIG_YAFFS_WINCE - yfsd_UnlockYAFFS(TRUE); -#endif - memcpy(localBuffer, buffer, dev->nDataBytesPerChunk); -#ifdef CONFIG_YAFFS_WINCE - yfsd_LockYAFFS(TRUE); -#endif - chunkWritten = - yaffs_WriteChunkDataToObject(in, chunk, localBuffer, - dev->nDataBytesPerChunk, - 0); - yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); -#else + chunkWritten = yaffs_WriteChunkDataToObject(in, chunk, buffer, dev->nDataBytesPerChunk, 0); -#endif + /* Since we've overwritten the cached data, we better invalidate it. */ yaffs_InvalidateChunkCache(in, chunk); } @@ -5215,8 +5213,7 @@ 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) +static int yaffs_UnlinkFileIfNeeded(yaffs_Object * in) { int retVal; @@ -5267,7 +5264,7 @@ int yaffs_DeleteFile(yaffs_Object * in) * That won't be the case if it has been resized to zero. */ if (!in->unlinked) { - retVal = yaffs_UnlinkFile(in); + retVal = yaffs_UnlinkFileIfNeeded(in); } if (retVal == YAFFS_OK && in->unlinked && !in->deleted) { in->deleted = deleted = 1; @@ -5312,32 +5309,48 @@ static int yaffs_DeleteHardLink(yaffs_Object * in) return yaffs_DoGenericObjectDeletion(in); } -static void yaffs_DestroyObject(yaffs_Object * obj) +int yaffs_DeleteObject(yaffs_Object * obj) { +int retVal = -1; switch (obj->variantType) { case YAFFS_OBJECT_TYPE_FILE: - yaffs_DeleteFile(obj); + retVal = yaffs_DeleteFile(obj); break; case YAFFS_OBJECT_TYPE_DIRECTORY: - yaffs_DeleteDirectory(obj); + return yaffs_DeleteDirectory(obj); break; case YAFFS_OBJECT_TYPE_SYMLINK: - yaffs_DeleteSymLink(obj); + retVal = yaffs_DeleteSymLink(obj); break; case YAFFS_OBJECT_TYPE_HARDLINK: - yaffs_DeleteHardLink(obj); + retVal = yaffs_DeleteHardLink(obj); break; case YAFFS_OBJECT_TYPE_SPECIAL: - yaffs_DoGenericObjectDeletion(obj); + retVal = yaffs_DoGenericObjectDeletion(obj); break; case YAFFS_OBJECT_TYPE_UNKNOWN: + retVal = 0; break; /* should not happen. */ } + + return retVal; } static int yaffs_UnlinkWorker(yaffs_Object * obj) { + int immediateDeletion = 0; + +#ifdef __KERNEL__ + if (!obj->myInode) { + immediateDeletion = 1; + } +#else + if (obj->inUse <= 0) { + immediateDeletion = 1; + } +#endif + if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { return yaffs_DeleteHardLink(obj); } else if (!ylist_empty(&obj->hardLinks)) { @@ -5373,10 +5386,10 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj) } return retVal; - } else { + } else if(immediateDeletion){ switch (obj->variantType) { case YAFFS_OBJECT_TYPE_FILE: - return yaffs_UnlinkFile(obj); + return yaffs_DeleteFile(obj); break; case YAFFS_OBJECT_TYPE_DIRECTORY: return yaffs_DeleteDirectory(obj); @@ -5392,6 +5405,9 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj) default: return YAFFS_FAIL; } + } else { + return yaffs_ChangeObjectName(obj, obj->myDev->unlinkedDir, + _Y("unlinked"), 0, 0); } } @@ -5441,6 +5457,8 @@ static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId, obj = yaffs_FindOrCreateObjectByNumber(dev, objId, YAFFS_OBJECT_TYPE_FILE); + if (!obj) + return; yaffs_AddObjectToDirectory(dev->unlinkedDir, obj); obj->variant.fileVariant.shrinkSize = 0; obj->valid = 1; /* So that we don't read any other info for this file */ @@ -5506,6 +5524,35 @@ struct yaffs_ShadowFixerStruct { struct yaffs_ShadowFixerStruct *next; }; + +static void yaffs_StripDeletedObjects(yaffs_Device *dev) +{ + /* + * Sort out state of unlinked and deleted objects after scanning. + */ + struct ylist_head *i; + struct ylist_head *n; + yaffs_Object *l; + + /* Soft delete all the unlinked files */ + ylist_for_each_safe(i, n, + &dev->unlinkedDir->variant.directoryVariant.children) { + if (i) { + l = ylist_entry(i, yaffs_Object, siblings); + yaffs_DeleteObject(l); + } + } + + ylist_for_each_safe(i, n, + &dev->deletedDir->variant.directoryVariant.children) { + if (i) { + l = ylist_entry(i, yaffs_Object, siblings); + yaffs_DeleteObject(l); + } + } + +} + static int yaffs_Scan(yaffs_Device * dev) { yaffs_ExtendedTags tags; @@ -5555,6 +5602,9 @@ static int yaffs_Scan(yaffs_Device * dev) bi->blockState = state; bi->sequenceNumber = sequenceNumber; + if(bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) + bi->blockState = state = YAFFS_BLOCK_STATE_DEAD; + T(YAFFS_TRACE_SCAN_DEBUG, (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, state, sequenceNumber)); @@ -5693,7 +5743,7 @@ static int yaffs_Scan(yaffs_Device * dev) * deleted, and worse still it has changed type. Delete the old object. */ - yaffs_DestroyObject(in); + yaffs_DeleteObject(in); in = 0; } @@ -5800,7 +5850,9 @@ static int yaffs_Scan(yaffs_Device * dev) yaffs_FindOrCreateObjectByNumber (dev, oh->parentObjectId, YAFFS_OBJECT_TYPE_DIRECTORY); - if (parent->variantType == + if(!parent) + alloc_failed = 1; + if (parent && parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN) { /* Set up as a directory */ parent->variantType = @@ -5808,7 +5860,7 @@ static int yaffs_Scan(yaffs_Device * dev) YINIT_LIST_HEAD(&parent->variant. directoryVariant. children); - } else if (parent->variantType != + } else if (!parent || parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { /* Hoosterman, another problem.... @@ -5906,25 +5958,6 @@ static int yaffs_Scan(yaffs_Device * dev) yaffs_HardlinkFixup(dev,hardList); - /* Handle the unlinked files. Since they were left in an unlinked state we should - * just delete them. - */ - { - struct ylist_head *i; - struct ylist_head *n; - - yaffs_Object *l; - /* Soft delete all the unlinked files */ - ylist_for_each_safe(i, n, - &dev->unlinkedDir->variant.directoryVariant. - children) { - if (i) { - l = ylist_entry(i, yaffs_Object, siblings); - yaffs_DestroyObject(l); - } - } - } - /* Fix up any shadowed objects */ { struct yaffs_ShadowFixerStruct *fixer; @@ -5938,7 +5971,7 @@ static int yaffs_Scan(yaffs_Device * dev) */ obj = yaffs_FindObjectByNumber(dev,fixer->shadowedId); if(obj) - yaffs_DestroyObject(obj); + yaffs_DeleteObject(obj); obj = yaffs_FindObjectByNumber(dev,fixer->objectId); if(obj){ @@ -6097,6 +6130,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT; + if(bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) + bi->blockState = state = YAFFS_BLOCK_STATE_DEAD; T(YAFFS_TRACE_SCAN_DEBUG, (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, @@ -6268,7 +6303,14 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) dev->nFreeChunks++; - } else if (tags.chunkId > 0) { + } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){ + T(YAFFS_TRACE_SCAN, + (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR), + blk, c)); + + dev->nFreeChunks++; + + }else if (tags.chunkId > 0) { /* chunkId > 0 so it is a data chunk... */ unsigned int endpos; __u32 chunkBase = @@ -6339,6 +6381,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) in = yaffs_FindOrCreateObjectByNumber (dev, tags.objectId, tags.extraObjectType); + if (!in) + alloc_failed = 1; } if (!in || @@ -6369,8 +6413,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) oh->isShrink = oh->inbandIsShrink; } - if (!in) + if (!in) { in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type); + if (!in) + alloc_failed = 1; + } } @@ -6380,7 +6427,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) (TSTR ("yaffs tragedy: Could not make object for object %d at chunk %d during scan" TENDSTR), tags.objectId, chunk)); - + continue; } if (in->valid) { @@ -6437,6 +6484,17 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) } + if (!in->valid && in->variantType != + (oh ? oh->type : tags.extraObjectType)) + T(YAFFS_TRACE_ERROR, ( + TSTR("yaffs tragedy: Bad object type, " + TCONT("%d != %d, for object %d at chunk ") + TCONT("%d during scan") + TENDSTR), oh ? + oh->type : tags.extraObjectType, + in->variantType, tags.objectId, + chunk)); + if (!in->valid && (tags.objectId == YAFFS_OBJECTID_ROOT || tags.objectId == @@ -6529,11 +6587,14 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) } in->dirty = 0; + if (!parent) + alloc_failed = 1; + /* directory stuff... * hook up to parent */ - if (parent->variantType == + if (parent && parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN) { /* Set up as a directory */ parent->variantType = @@ -6541,7 +6602,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) YINIT_LIST_HEAD(&parent->variant. directoryVariant. children); - } else if (parent->variantType != + } else if (!parent || parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { /* Hoosterman, another problem.... @@ -6656,37 +6717,6 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) */ yaffs_HardlinkFixup(dev,hardList); - - /* - * Sort out state of unlinked and deleted objects. - */ - { - struct ylist_head *i; - struct ylist_head *n; - - yaffs_Object *l; - - /* Soft delete all the unlinked files */ - ylist_for_each_safe(i, n, - &dev->unlinkedDir->variant.directoryVariant. - children) { - if (i) { - l = ylist_entry(i, yaffs_Object, siblings); - yaffs_DestroyObject(l); - } - } - - /* Soft delete all the deletedDir files */ - ylist_for_each_safe(i, n, - &dev->deletedDir->variant.directoryVariant. - children) { - if (i) { - l = ylist_entry(i, yaffs_Object, siblings); - yaffs_DestroyObject(l); - - } - } - } yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); @@ -6711,6 +6741,7 @@ static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) if(!obj){ T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR))); YBUG(); + return; } if(yaffs_SkipVerification(obj->myDev)) @@ -6719,6 +6750,7 @@ static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) if(!obj->parent){ T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR))); YBUG(); + return; } if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){ @@ -6750,8 +6782,10 @@ static void yaffs_VerifyDirectory(yaffs_Object *directory) struct ylist_head *lh; yaffs_Object *listObj; - if(!directory) + if(!directory){ YBUG(); + return; + } if(yaffs_SkipFullVerification(directory->myDev)) return; @@ -6768,7 +6802,7 @@ static void yaffs_VerifyDirectory(yaffs_Object *directory) if (lh) { listObj = ylist_entry(lh, yaffs_Object, siblings); if(listObj->parent != directory){ - T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent" TENDSTR),listObj->parent)); + T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR),listObj->parent)); YBUG(); } yaffs_VerifyObjectInDirectory(listObj); @@ -6810,6 +6844,7 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory, ("tragedy: Trying to add an object to a null pointer directory" TENDSTR))); YBUG(); + return; } if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { T(YAFFS_TRACE_ALWAYS, @@ -6870,6 +6905,7 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, ("tragedy: yaffs_FindObjectByName: null pointer directory" TENDSTR))); YBUG(); + return NULL; } if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { T(YAFFS_TRACE_ALWAYS, @@ -6925,12 +6961,14 @@ int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, ("tragedy: yaffs_FindObjectByName: null pointer directory" TENDSTR))); YBUG(); + return YAFFS_FAIL; } if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { T(YAFFS_TRACE_ALWAYS, (TSTR ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR))); YBUG(); + return YAFFS_FAIL; } ylist_for_each(i, &theDir->variant.directoryVariant.children) { @@ -7499,6 +7537,8 @@ int yaffs_GutsInitialise(yaffs_Device * dev) }else if(!yaffs_Scan(dev)) init_failed = 1; + + yaffs_StripDeletedObjects(dev); } if(init_failed){