⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yaffs_guts.c

📁 yaffs2 source code for linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		 	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 %x obj %x oh %x"TENDSTR),		 		(__u32)tags,(__u32)obj,(__u32)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));}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<<YAFFS_TNODES_INTERNAL_BITS) + i);				}			}		} else if (level == 0) {			yaffs_ExtendedTags tags;			__u32 objectId = obj->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;}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;		if(requiredTallness > actualTallness )		T(YAFFS_TRACE_VERIFY,		(TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),		 obj->objectId,actualTallness, requiredTallness));			/* 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 chunkIsLive;		if(!obj)		return;		dev = obj->myDev;		if(yaffs_SkipVerification(dev))		return;			/* Check sane object header chunk */	chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;	chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;	chunkIdOk = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);	chunkIsLive = chunkIdOk &&			yaffs_CheckChunkBit(dev,					    obj->hdrChunk / dev->nChunksPerBlock,					    obj->hdrChunk % dev->nChunksPerBlock);	if(!obj->fake &&	    (!chunkIdOk || !chunkIsLive)) {	   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"));	}		if(chunkIdOk && chunkIsLive &&!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;	}		}static 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);                        }                }	 }}/* *  Simple hash function. Needs to have a reasonable spread */ static Y_INLINE int yaffs_HashFunction(int n){	n = abs(n);	return (n % YAFFS_NOBJECT_BUCKETS);}/* * Access functions to useful fake objects. * Note that root might have a presence in NAND if permissions are set. */ yaffs_Object *yaffs_Root(yaffs_Device * dev){	return dev->rootDir;}yaffs_Object *yaffs_LostNFound(yaffs_Device * dev){	return dev->lostNFoundDir;}/* *  Erased NAND checking functions */ int yaffs_CheckFF(__u8 * buffer, int nBytes){	/* Horrible, slow implementation */	while (nBytes--) {		if (*buffer != 0xFF)			return 0;		buffer++;	}	return 1;}static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,				  int chunkInNAND){	int retval = YAFFS_OK;	__u8 *data = yaffs_GetTempBuffer(dev, __LINE__);	yaffs_ExtendedTags tags;	int result;	result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);		if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)		retval = YAFFS_FAIL;			if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {		T(YAFFS_TRACE_NANDACCESS,		  (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND));		retval = YAFFS_FAIL;	}	yaffs_ReleaseTempBuffer(dev, data, __LINE__);	return retval;}static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,					     const __u8 * data,					     yaffs_ExtendedTags * tags,					     int useReserve){	int attempts = 0;	int writeOk = 0;	int chunk;	yaffs_InvalidateCheckpoint(dev);	do {		yaffs_BlockInfo *bi = 0;		int erasedOk = 0;		chunk = yaffs_AllocateChunk(dev, useReserve, &bi);		if (chunk < 0) {			/* no space */			break;		}		/* First check this chunk is erased, if it needs		 * checking.  The checking policy (unless forced		 * always on) is as follows:		 *		 * Check the first page we try to write in a block.		 * If the check passes then we don't need to check any		 * more.	If the check fails, we check again...		 * If the block has been erased, we don't need to check.		 *		 * However, if the block has been prioritised for gc,		 * then we think there might be something odd about		 * this block and stop using it.		 *		 * Rationale: We should only ever see chunks that have		 * not been erased if there was a partially written		 * 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.		 */		if (bi->gcPrioritise) {			yaffs_DeleteChunk(dev, chunk, 1, __LINE__);			/* try another chunk */			continue;		}		/* let's give it a try */		attempts++;#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED		bi->skipErasedCheck = 0;#endif		if (!bi->skipErasedCheck) {			erasedOk = yaffs_CheckChunkErased(dev, chunk);			if (erasedOk != YAFFS_OK) {				T(YAFFS_TRACE_ERROR,				(TSTR ("**>> yaffs chunk %d was not erased"				TENDSTR), chunk));				/* try another chunk */				continue;			}			bi->skipErasedCheck = 1;		}		writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk,				data, tags);		if (writeOk != YAFFS_OK) {			yaffs_HandleWriteChunkError(dev, chunk, erasedOk);			/* try another chunk */			continue;		}		/* Copy the data into the robustification buffer */		yaffs_HandleWriteChunkOk(dev, chunk, data, tags);	} while (writeOk != YAFFS_OK && 	        (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));		if(!writeOk)		chunk = -1;	if (attempts > 1) {		T(YAFFS_TRACE_ERROR,			(TSTR("**>> yaffs write required %d attempts" TENDSTR),			attempts));		dev->nRetriedWrites += (attempts - 1);	}	return chunk;}/* * Block retiring for handling a broken block. */ static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND){	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);	yaffs_InvalidateCheckpoint(dev);		yaffs_MarkBlockBad(dev, blockInNAND);	bi->blockState = YAFFS_BLOCK_STATE_DEAD;	bi->gcPrioritise = 0;	bi->needsRetiring = 0;	dev->nRetiredBlocks++;}/* * Functions for robustisizing TODO * */ static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,				     const __u8 * data,				     const yaffs_ExtendedTags * tags){}static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,				    const yaffs_ExtendedTags * tags){}void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi){	if(!bi->gcPrioritise){		bi->gcPrioritise = 1;		dev->hasPendingPrioritisedGCs = 1;		bi->chunkErrorStrikes ++;				if(bi->chunkErrorStrikes > 3){			bi->needsRetiring = 1; /* Too many stikes, so retire this */			T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));		}			}}static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -