X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.c;h=a8b850a71711dda636dc3dd330f5576f0d9c6f2b;hp=6efa94f57d268a8b4d2beddbcdb996eb20907024;hb=bfb36fe45ceea5a7e8347b24a575ab627e60df94;hpb=780469359d1051ab37ab281b0520137d73fee2e9;ds=sidebyside diff --git a/yaffs_guts.c b/yaffs_guts.c index 6efa94f..a8b850a 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -25,6 +25,7 @@ #include "yaffs_yaffs1.h" #include "yaffs_yaffs2.h" #include "yaffs_bitmap.h" +#include "yaffs_verify.h" #include "yaffs_nand.h" #include "yaffs_packedtags2.h" @@ -87,25 +88,12 @@ static int yaffs_AllocateChunk(yaffs_Device *dev, int useReserve, 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 -#define yaffs_CheckFileSanity(in) -#endif - static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in); static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId); static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode, yaffs_ExtendedTags *tags); -static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, - unsigned pos); -static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, - yaffs_FileStructure *fStruct, - __u32 chunkId); - static int yaffs_VerifyChunkWritten(yaffs_Device *dev, int chunkInNAND, const __u8 *data, @@ -301,460 +289,7 @@ int yaffs_IsManagedTempBuffer(yaffs_Device *dev, const __u8 *buffer) * Verification code */ -static int yaffs_SkipVerification(yaffs_Device *dev) -{ - dev=dev; - return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL)); -} -static int yaffs_SkipFullVerification(yaffs_Device *dev) -{ - dev=dev; - return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL)); -} - -static int yaffs_SkipNANDVerification(yaffs_Device *dev) -{ - dev=dev; - return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); -} - -static const char *blockStateName[] = { -"Unknown", -"Needs scanning", -"Scanning", -"Empty", -"Allocating", -"Full", -"Dirty", -"Checkpoint", -"Collecting", -"Dead" -}; - - -static void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n) -{ - int actuallyUsed; - int inUse; - - if (yaffs_SkipVerification(dev)) - return; - - /* Report illegal runtime 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) { - case YAFFS_BLOCK_STATE_UNKNOWN: - case YAFFS_BLOCK_STATE_SCANNING: - case YAFFS_BLOCK_STATE_NEEDS_SCANNING: - T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has bad run-state %s"TENDSTR), - n, blockStateName[bi->blockState])); - } - - /* Check pages in use and soft deletions are legal */ - - actuallyUsed = bi->pagesInUse - bi->softDeletions; - - if (bi->pagesInUse < 0 || bi->pagesInUse > dev->param.nChunksPerBlock || - bi->softDeletions < 0 || bi->softDeletions > dev->param.nChunksPerBlock || - actuallyUsed < 0 || actuallyUsed > dev->param.nChunksPerBlock) - T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR), - n, bi->pagesInUse, bi->softDeletions)); - - - /* Check chunk bitmap legal */ - inUse = yaffs_CountChunkBits(dev, n); - if (inUse != bi->pagesInUse) - T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR), - n, bi->pagesInUse, inUse)); - - /* Check that the sequence number is valid. - * Ten million is legal, but is very unlikely - */ - - yaffs2_VerifyBlock(dev,bi,n); -} - - - -static void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, - int n) -{ - yaffs_VerifyBlock(dev, bi, n); - - /* After collection the block should be in the erased state */ - /* This will need to change if we do partial gc */ - - 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)); - } -} - -void yaffs_VerifyBlocks(yaffs_Device *dev) -{ - int i; - int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES]; - int nIllegalBlockStates = 0; - - if (yaffs_SkipVerification(dev)) - return; - - memset(nBlocksPerState, 0, sizeof(nBlocksPerState)); - - for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); - yaffs_VerifyBlock(dev, bi, i); - - if (bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) - nBlocksPerState[bi->blockState]++; - else - nIllegalBlockStates++; - } - - T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR))); - T(YAFFS_TRACE_VERIFY, (TSTR("Block summary"TENDSTR))); - - T(YAFFS_TRACE_VERIFY, (TSTR("%d blocks have illegal states"TENDSTR), nIllegalBlockStates)); - if (nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1) - T(YAFFS_TRACE_VERIFY, (TSTR("Too many allocating blocks"TENDSTR))); - - for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) - T(YAFFS_TRACE_VERIFY, - (TSTR("%s %d blocks"TENDSTR), - blockStateName[i], nBlocksPerState[i])); - - if (dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]) - T(YAFFS_TRACE_VERIFY, - (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR), - dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])); - - if (dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]) - T(YAFFS_TRACE_VERIFY, - (TSTR("Erased block count wrong dev %d count %d"TENDSTR), - dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])); - - if (nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1) - T(YAFFS_TRACE_VERIFY, - (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR), - nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING])); - - T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR))); - -} - -/* - * Verify the object header. oh must be valid, but obj and tags may be NULL in which - * case those tests will not be performed. - */ -static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck) -{ - if (obj && yaffs_SkipVerification(obj->myDev)) - return; - - if (!(tags && obj && oh)) { - T(YAFFS_TRACE_VERIFY, - (TSTR("Verifying object header tags %p obj %p oh %p"TENDSTR), - tags, obj, oh)); - return; - } - - if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || - oh->type > YAFFS_OBJECT_TYPE_MAX) - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), - tags->objectId, oh->type)); - - if (tags->objectId != obj->objectId) - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d header mismatch objectId %d"TENDSTR), - tags->objectId, obj->objectId)); - - - /* - * Check that the object's parent ids match if parentCheck requested. - * - * Tests do not apply to the root object. - */ - - if (parentCheck && tags->objectId > 1 && !obj->parent) - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR), - tags->objectId, oh->parentObjectId)); - - if (parentCheck && obj->parent && - oh->parentObjectId != obj->parent->objectId && - (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED || - obj->parent->objectId != YAFFS_OBJECTID_DELETED)) - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR), - tags->objectId, oh->parentObjectId, obj->parent->objectId)); - - if (tags->objectId > 1 && oh->name[0] == 0) /* Null name */ - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d header name is NULL"TENDSTR), - obj->objectId)); - - if (tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */ - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d header name is 0xFF"TENDSTR), - obj->objectId)); -} - - -#if 0 -/* Not being used, but don't want to throw away yet */ -static int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn, - __u32 level, int chunkOffset) -{ - int i; - yaffs_Device *dev = obj->myDev; - int ok = 1; - - if (tn) { - if (level > 0) { - - for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) { - if (tn->internal[i]) { - ok = yaffs_VerifyTnodeWorker(obj, - tn->internal[i], - level - 1, - (chunkOffset<objectId; - - chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS; - - for (i = 0; i < YAFFS_NTNODES_LEVEL0; i++) { - __u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i); - - if (theChunk > 0) { - /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */ - yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags); - if (tags.objectId != objectId || tags.chunkId != chunkOffset) { - T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), - objectId, chunkOffset, theChunk, - tags.objectId, tags.chunkId)); - } - } - chunkOffset++; - } - } - } - - return ok; - -} - -#endif - -static void yaffs_VerifyFile(yaffs_Object *obj) -{ - int requiredTallness; - int actualTallness; - __u32 lastChunk; - __u32 x; - __u32 i; - yaffs_Device *dev; - yaffs_ExtendedTags tags; - yaffs_Tnode *tn; - __u32 objectId; - - if (!obj) - return; - - if (yaffs_SkipVerification(obj->myDev)) - return; - - dev = obj->myDev; - objectId = obj->objectId; - - /* Check file size is consistent with tnode depth */ - lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1; - x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS; - requiredTallness = 0; - while (x > 0) { - x >>= YAFFS_TNODES_INTERNAL_BITS; - requiredTallness++; - } - - actualTallness = obj->variant.fileVariant.topLevel; - - /* Check that the chunks in the tnode tree are all correct. - * We do this by scanning through the tnode tree and - * checking the tags for every chunk match. - */ - - if (yaffs_SkipNANDVerification(dev)) - return; - - for (i = 1; i <= lastChunk; i++) { - tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant, i); - - if (tn) { - __u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i); - if (theChunk > 0) { - /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */ - yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags); - if (tags.objectId != objectId || tags.chunkId != i) { - T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), - objectId, i, theChunk, - tags.objectId, tags.chunkId)); - } - } - } - } -} - - -static void yaffs_VerifyHardLink(yaffs_Object *obj) -{ - if (obj && yaffs_SkipVerification(obj->myDev)) - return; - - /* Verify sane equivalent object */ -} - -static void yaffs_VerifySymlink(yaffs_Object *obj) -{ - if (obj && yaffs_SkipVerification(obj->myDev)) - return; - - /* Verify symlink string */ -} - -static void yaffs_VerifySpecial(yaffs_Object *obj) -{ - if (obj && yaffs_SkipVerification(obj->myDev)) - return; -} - -static void yaffs_VerifyObject(yaffs_Object *obj) -{ - yaffs_Device *dev; - - __u32 chunkMin; - __u32 chunkMax; - - __u32 chunkIdOk; - __u32 chunkInRange; - __u32 chunkShouldNotBeDeleted; - __u32 chunkValid; - - if (!obj) - return; - - if (obj->beingCreated) - return; - - dev = obj->myDev; - - if (yaffs_SkipVerification(dev)) - return; - - /* Check sane object header chunk */ - - chunkMin = dev->internalStartBlock * dev->param.nChunksPerBlock; - chunkMax = (dev->internalEndBlock+1) * dev->param.nChunksPerBlock - 1; - - chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax); - chunkIdOk = chunkInRange || (obj->hdrChunk == 0); - chunkValid = chunkInRange && - yaffs_CheckChunkBit(dev, - obj->hdrChunk / dev->param.nChunksPerBlock, - obj->hdrChunk % dev->param.nChunksPerBlock); - chunkShouldNotBeDeleted = chunkInRange && !chunkValid; - - if (!obj->fake && - (!chunkIdOk || chunkShouldNotBeDeleted)) { - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), - obj->objectId, obj->hdrChunk, - chunkIdOk ? "" : ",out of range", - chunkShouldNotBeDeleted ? ",marked as deleted" : "")); - } - - if (chunkValid && !yaffs_SkipNANDVerification(dev)) { - yaffs_ExtendedTags tags; - yaffs_ObjectHeader *oh; - __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); - - oh = (yaffs_ObjectHeader *)buffer; - - yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk, buffer, - &tags); - - yaffs_VerifyObjectHeader(obj, oh, &tags, 1); - - yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); - } - - /* Verify it has a parent */ - if (obj && !obj->fake && - (!obj->parent || obj->parent->myDev != dev)) { - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR), - obj->objectId, obj->parent)); - } - - /* Verify parent is a directory */ - if (obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR), - obj->objectId, obj->parent->variantType)); - } - - switch (obj->variantType) { - case YAFFS_OBJECT_TYPE_FILE: - yaffs_VerifyFile(obj); - break; - case YAFFS_OBJECT_TYPE_SYMLINK: - yaffs_VerifySymlink(obj); - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: - yaffs_VerifyDirectory(obj); - break; - case YAFFS_OBJECT_TYPE_HARDLINK: - yaffs_VerifyHardLink(obj); - break; - case YAFFS_OBJECT_TYPE_SPECIAL: - yaffs_VerifySpecial(obj); - break; - case YAFFS_OBJECT_TYPE_UNKNOWN: - default: - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d has illegaltype %d"TENDSTR), - obj->objectId, obj->variantType)); - break; - } -} - -void yaffs_VerifyObjects(yaffs_Device *dev) -{ - yaffs_Object *obj; - int i; - struct ylist_head *lh; - - if (yaffs_SkipVerification(dev)) - return; - - /* Iterate through the objects in each hash entry */ - - for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { - ylist_for_each(lh, &dev->objectBucket[i].list) { - if (lh) { - obj = ylist_entry(lh, yaffs_Object, hashLink); - yaffs_VerifyObject(obj); - } - } - } -} /* @@ -1154,7 +689,7 @@ void yaffs_LoadLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, } } -static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, +__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) { __u32 *map = (__u32 *)tn; @@ -1191,7 +726,7 @@ static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, */ /* FindLevel0Tnode finds the level 0 tnode, if one exists. */ -static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, +yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId) { @@ -3152,63 +2687,6 @@ static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in, int chunkInInode, return retVal; } -#ifdef YAFFS_PARANOID - -static int yaffs_CheckFileSanity(yaffs_Object *in) -{ - int chunk; - int nChunks; - int fSize; - int failed = 0; - int objId; - yaffs_Tnode *tn; - yaffs_Tags localTags; - yaffs_Tags *tags = &localTags; - int theChunk; - int chunkDeleted; - - if (in->variantType != YAFFS_OBJECT_TYPE_FILE) - return YAFFS_FAIL; - - objId = in->objectId; - fSize = in->variant.fileVariant.fileSize; - nChunks = - (fSize + in->myDev->nDataBytesPerChunk - 1) / in->myDev->nDataBytesPerChunk; - - for (chunk = 1; chunk <= nChunks; chunk++) { - tn = yaffs_FindLevel0Tnode(in->myDev, &in->variant.fileVariant, - chunk); - - if (tn) { - - theChunk = yaffs_GetChunkGroupBase(dev, tn, chunk); - - if (yaffs_CheckChunkBits - (dev, theChunk / dev->param.nChunksPerBlock, - theChunk % dev->param.nChunksPerBlock)) { - - yaffs_ReadChunkTagsFromNAND(in->myDev, theChunk, - tags, - &chunkDeleted); - if (yaffs_TagsMatch - (tags, in->objectId, chunk, chunkDeleted)) { - /* found it; */ - - } - } else { - - failed = 1; - } - - } else { - /* T(("No level 0 found for %d\n", chunk)); */ - } - } - - return failed ? YAFFS_FAIL : YAFFS_OK; -} - -#endif int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, int chunkInNAND, int inScan) @@ -3475,7 +2953,7 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object *in, int chunkInInode, if (prevChunkId > 0) yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__); - yaffs_CheckFileSanity(in); + yaffs_VerifyFileSanity(in); } return newChunkId; @@ -4887,82 +4365,6 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in) /*------------------------------ Directory Functions ----------------------------- */ -static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) -{ - struct ylist_head *lh; - yaffs_Object *listObj; - - int count = 0; - - if (!obj) { - T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR))); - YBUG(); - return; - } - - if (yaffs_SkipVerification(obj->myDev)) - return; - - if (!obj->parent) { - T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR))); - YBUG(); - return; - } - - 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 */ - - 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) { - T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR), count)); - YBUG(); - } -} - -static void yaffs_VerifyDirectory(yaffs_Object *directory) -{ - struct ylist_head *lh; - yaffs_Object *listObj; - - if (!directory) { - YBUG(); - return; - } - - if (yaffs_SkipFullVerification(directory->myDev)) - return; - - 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) { - T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR), listObj->parent)); - YBUG(); - } - yaffs_VerifyObjectInDirectory(listObj); - } - } -} - /* *yaffs_UpdateParent() handles fixing a directories mtime and ctime when a new * link (ie. name) is created or deleted in the directory. @@ -5902,7 +5304,7 @@ void yaffs_Deinitialise(yaffs_Device *dev) } } -static int yaffs_CountFreeChunks(yaffs_Device *dev) +int yaffs_CountFreeChunks(yaffs_Device *dev) { int nFree=0; int b; @@ -5969,27 +5371,6 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) } -static int yaffs_freeVerificationFailures; - -void yaffs_VerifyFreeChunks(yaffs_Device *dev) -{ - int counted; - int difference; - - if (yaffs_SkipVerification(dev)) - return; - - counted = yaffs_CountFreeChunks(dev); - - difference = dev->nFreeChunks - counted; - - if (difference) { - T(YAFFS_TRACE_ALWAYS, - (TSTR("Freechunks verification failure %d %d %d" TENDSTR), - dev->nFreeChunks, counted, difference)); - yaffs_freeVerificationFailures++; - } -} /*---------------------------------------- YAFFS test code ----------------------*/