X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=76074cd51d8b689363a17fcb9a944f6d9af5bf0f;hp=34e94a0a93942b2b931026beef9fa8e31624bc53;hb=8642921e20e15e95736ea7821f450ac2cb6d92b2;hpb=5b88de3db784f69899f8f02d0114d03c4cdba354 diff --git a/yaffs_guts.c b/yaffs_guts.c index 34e94a0..76074cd 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -11,8 +11,9 @@ * published by the Free Software Foundation. */ + const char *yaffs_guts_c_version = - "$Id: yaffs_guts.c,v 1.67 2008-11-27 02:46:45 charles Exp $"; + "$Id: yaffs_guts.c,v 1.72 2009-01-16 00:44:45 charles Exp $"; #include "yportenv.h" @@ -406,14 +407,11 @@ static int yaffs_SkipVerification(yaffs_Device *dev) return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); } -#if 0 static int yaffs_SkipFullVerification(yaffs_Device *dev) { return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL)); } -#endif - static int yaffs_SkipNANDVerification(yaffs_Device *dev) { return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); @@ -485,9 +483,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)); } @@ -4365,7 +4364,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); @@ -4414,7 +4412,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); @@ -4849,7 +4846,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; @@ -4879,9 +4877,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; @@ -4889,7 +4890,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; @@ -5509,6 +5513,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_DestroyObject(l); + } + } + + ylist_for_each_safe(i, n, + &dev->deletedDir->variant.directoryVariant.children) { + if (i) { + l = ylist_entry(i, yaffs_Object, siblings); + yaffs_DestroyObject(l); + } + } + +} + static int yaffs_Scan(yaffs_Device * dev) { yaffs_ExtendedTags tags; @@ -5909,25 +5942,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; @@ -6271,7 +6285,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev) dev->nFreeChunks++; - } else if (tags.chunkId > 0) { + } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){ + printf("Error in ECC\n"); + /* Don't actually delete because the chunk is not yet set up as being in use */ + /* yaffs_DeleteChunk(dev, chunk, 1, __LINE__); */ + }else if (tags.chunkId > 0) { /* chunkId > 0 so it is a data chunk... */ unsigned int endpos; __u32 chunkBase = @@ -6659,37 +6677,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,17 +6698,23 @@ static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) int count = 0; - if(!obj) + if(!obj){ + T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR))); YBUG(); + } if(yaffs_SkipVerification(obj->myDev)) return; - if(!obj->parent) + if(!obj->parent){ + T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR))); YBUG(); + } - if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){ + T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR))); YBUG(); + } /* Iterate through the objects in each hash entry */ @@ -6734,9 +6727,10 @@ static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) } } - if(count != 1) - YBUG(); - + if(count != 1){ + T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR),count)); + YBUG(); + } } @@ -6749,20 +6743,24 @@ static void yaffs_VerifyDirectory(yaffs_Object *directory) if(!directory) YBUG(); - if(yaffs_SkipVerification(directory->myDev)) + if(yaffs_SkipFullVerification(directory->myDev)) return; - if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) + if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){ + T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR),directory->variantType)); 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) + if(listObj->parent != directory){ + T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR),listObj->parent)); YBUG(); + } yaffs_VerifyObjectInDirectory(listObj); } } @@ -7491,6 +7489,8 @@ int yaffs_GutsInitialise(yaffs_Device * dev) }else if(!yaffs_Scan(dev)) init_failed = 1; + + yaffs_StripDeletedObjects(dev); } if(init_failed){