X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=0bab9cf00f5ea6f8c67146835ff82b048912ffac;hp=a51d82d6aa5d6df0aac9cde72dbab396bc2e564c;hb=f66be08746927c4dd5ac8daeb6f72c8f5386277c;hpb=ea3c314412ed2ecee3f47b576d5759267173e9c0 diff --git a/yaffs_guts.c b/yaffs_guts.c index a51d82d..0bab9cf 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.98 2009-12-07 01:17:33 charles Exp $"; + "$Id: yaffs_guts.c,v 1.100 2009-12-22 04:09:06 charles Exp $"; #include "yportenv.h" @@ -113,6 +113,12 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId); +static void yaffs_SkipRestOfBlock(yaffs_Device *dev); +static int yaffs_VerifyChunkWritten(yaffs_Device *dev, + int chunkInNAND, + const __u8 *data, + yaffs_ExtendedTags *tags); + /* Function to calculate chunk and offset */ static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, @@ -548,8 +554,8 @@ static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, if (!(tags && obj && oh)) { T(YAFFS_TRACE_VERIFY, - (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), - (__u32)tags, (__u32)obj, (__u32)oh)); + (TSTR("Verifying object header tags %p obj %p oh %p"TENDSTR), + tags, obj, oh)); return; } @@ -918,6 +924,29 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, } + +static int yaffs_VerifyChunkWritten(yaffs_Device *dev, + int chunkInNAND, + const __u8 *data, + yaffs_ExtendedTags *tags) +{ + int retval = YAFFS_OK; + yaffs_ExtendedTags tempTags; + __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); + int result; + + result = yaffs_ReadChunkWithTagsFromNAND(dev,chunkInNAND,buffer,&tempTags); + if(memcmp(buffer,data,dev->nDataBytesPerChunk) || + tempTags.objectId != tags->objectId || + tempTags.chunkId != tags->chunkId || + tempTags.byteCount != tags->byteCount) + retval = YAFFS_FAIL; + + yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); + + return retval; +} + static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_ExtendedTags *tags, @@ -957,12 +986,11 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, * chunk due to power loss. This checking policy should * catch that case with very few checks and thus save a * lot of checks that are most likely not needed. + * + * Mods to the above + * If an erase check fails or the write fails we skip the + * rest of the block. */ - if (bi->gcPrioritise) { - yaffs_DeleteChunk(dev, chunk, 1, __LINE__); - /* try another chunk */ - continue; - } /* let's give it a try */ attempts++; @@ -977,20 +1005,30 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, (TSTR("**>> yaffs chunk %d was not erased" TENDSTR), chunk)); - /* try another chunk */ + /* If not erased, delete this one, + * skip rest of block and + * try another chunk */ + yaffs_DeleteChunk(dev,chunk,1,__LINE__); + yaffs_SkipRestOfBlock(dev); continue; } - bi->skipErasedCheck = 1; } writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk, data, tags); + + if(!bi->skipErasedCheck) + writeOk = yaffs_VerifyChunkWritten(dev, chunk, data, tags); + if (writeOk != YAFFS_OK) { + /* Clean up aborted write, skip to next block and + * try another chunk */ yaffs_HandleWriteChunkError(dev, chunk, erasedOk); - /* try another chunk */ continue; } + bi->skipErasedCheck = 1; + /* Copy the data into the robustification buffer */ yaffs_HandleWriteChunkOk(dev, chunk, data, tags); @@ -1100,6 +1138,7 @@ static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, /* Delete the chunk */ yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__); + yaffs_SkipRestOfBlock(dev); } @@ -2979,6 +3018,22 @@ static int yaffs_GetErasedChunks(yaffs_Device *dev) } +/* + * yaffs_SkipRestOfBlock() skips over the rest of the allocation block + * if we don't want to write to it. + */ +static void yaffs_SkipRestOfBlock(yaffs_Device *dev) +{ + if(dev->allocationBlock > 0){ + yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->allocationBlock); + if(bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING){ + bi->blockState = YAFFS_BLOCK_STATE_FULL; + dev->allocationBlock = -1; + } + } +} + + static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, int wholeBlock) { @@ -4464,8 +4519,8 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev) cp.structType = sizeof(cp); 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.hdrChunk, (unsigned) obj)); + TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %p" TENDSTR), + cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk, obj)); ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); @@ -4498,7 +4553,7 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev) ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); if (cp.structType != sizeof(cp)) { T(YAFFS_TRACE_CHECKPOINT, (TSTR("struct size %d instead of %d ok %d"TENDSTR), - cp.structType, sizeof(cp), ok)); + cp.structType, (int)sizeof(cp), ok)); ok = 0; } @@ -5758,7 +5813,7 @@ static int yaffs_Scan(yaffs_Device *dev) dev->allocationBlock = blk; dev->allocationPage = c; dev->allocationBlockFinder = blk; - /* Set it to here to encourage the allocator to go forth from here. */ + /* Set block finder here to encourage the allocator to go forth from here. */ } @@ -6004,12 +6059,6 @@ static int yaffs_Scan(yaffs_Device *dev) break; } -/* - if (parent == dev->deletedDir) { - yaffs_DestroyObject(in); - bi->hasShrinkHeader = 1; - } -*/ } } } @@ -6019,6 +6068,12 @@ static int yaffs_Scan(yaffs_Device *dev) state = YAFFS_BLOCK_STATE_FULL; } + if (state == YAFFS_BLOCK_STATE_ALLOCATING) { + /* If the block was partially allocated then treat it as fully allocated.*/ + state = YAFFS_BLOCK_STATE_FULL; + dev->allocationBlock = -1; + } + bi->blockState = state; /* Now let's see if it was dirty */ @@ -6361,13 +6416,9 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) dev->allocationBlockFinder = blk; } else { /* This is a partially written block that is not - * the current allocation block. This block must have - * had a write failure, so set up for retirement. + * the current allocation block. */ - /* bi->needsRetiring = 1; ??? TODO */ - bi->gcPrioritise = 1; - T(YAFFS_TRACE_ALWAYS, (TSTR("Partially written block %d detected" TENDSTR), blk)); @@ -6629,6 +6680,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) oh-> shadowsObject, 1); + yaffs_SetObjectName(in, oh->name); @@ -6760,6 +6812,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) state = YAFFS_BLOCK_STATE_FULL; } + bi->blockState = state; /* Now let's see if it was dirty */ @@ -6770,6 +6823,8 @@ static int yaffs_ScanBackwards(yaffs_Device *dev) } } + + yaffs_SkipRestOfBlock(dev); if (altBlockIndex) YFREE_ALT(blockIndex); @@ -7766,7 +7821,7 @@ static void yaffs_VerifyFreeChunks(yaffs_Device *dev) do { \ if (sizeof(structure) != syze) { \ T(YAFFS_TRACE_ALWAYS, (TSTR("%s should be %d but is %d\n" TENDSTR),\ - name, syze, sizeof(structure))); \ + name, syze, (int) sizeof(structure))); \ return YAFFS_FAIL; \ } \ } while (0) @@ -7777,7 +7832,7 @@ static int yaffs_CheckStructures(void) /* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */ /* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */ #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG - yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); +/* yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); */ #endif #ifndef CONFIG_YAFFS_WINCE yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");