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

📄 yaffs_guts.c

📁 YAFFS
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * YAFFS: Yet another FFS. A NAND-flash specific file system.  * * Copyright (C) 2002 Aleph One Ltd. *   for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning <charles@aleph1.co.uk> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */const char *yaffs_guts_c_version =    "$Id: yaffs_guts.c,v 1.27 2005/12/20 04:02:18 charles Exp $";#include "yportenv.h"#include "yaffsinterface.h"#include "yaffs_guts.h"#include "yaffs_tagsvalidity.h"#include "yaffs_tagscompat.h"#ifdef CONFIG_YAFFS_WINCEvoid yfsd_LockYAFFS(BOOL fsLockOnly);void yfsd_UnlockYAFFS(BOOL fsLockOnly);#endif#define YAFFS_PASSIVE_GC_CHUNKS 2#include "yaffs_ecc.h"/* NAND access */static Y_INLINE int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev,						    int chunkInNAND,						    __u8 * buffer,						    yaffs_ExtendedTags * tags);static Y_INLINE int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,						   int chunkInNAND,						   const __u8 * data,						   yaffs_ExtendedTags * tags);static Y_INLINE int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo);static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device * dev,						 int blockNo,						 yaffs_BlockState * state,						 unsigned *sequenceNumber);/* Robustification (if it ever comes about...) */static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND);static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND);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);/* Other local prototypes */static int yaffs_UnlinkObject( yaffs_Object *obj);static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev,					     const __u8 * buffer,					     yaffs_ExtendedTags * tags,					     int useReserve);static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,				  int chunkInNAND, int inScan);static yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,					   yaffs_ObjectType type);static void yaffs_AddObjectToDirectory(yaffs_Object * directory,				       yaffs_Object * obj);static int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name,				    int force, int isShrink, int shadows);static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj);static int yaffs_CheckStructures(void);static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,			      int chunkOffset, int *limit);static int yaffs_DoGenericObjectDeletion(yaffs_Object * in);static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,				    int lineNo);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);loff_t yaffs_GetFileSize(yaffs_Object * obj);static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve);static void yaffs_VerifyFreeChunks(yaffs_Device * dev);#ifdef YAFFS_PARANOIDstatic int yaffs_CheckFileSanity(yaffs_Object * in);#else#define yaffs_CheckFileSanity(in)#endifstatic void yaffs_InvalidateWholeChunkCache(yaffs_Object * in);static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId);/* *   Start of real code. *//* * NAND access layer */ static int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,					   __u8 * buffer,					   yaffs_ExtendedTags * tags){	chunkInNAND -= dev->chunkOffset;	if (dev->readChunkWithTagsFromNAND)		return dev->readChunkWithTagsFromNAND(dev, chunkInNAND, buffer,						      tags);	else		return yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,									chunkInNAND,									buffer,									tags);}static Y_INLINE int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,						   int chunkInNAND,						   const __u8 * buffer,						   yaffs_ExtendedTags * tags){	chunkInNAND -= dev->chunkOffset;	if (tags) {		tags->sequenceNumber = dev->sequenceNumber;		tags->chunkUsed = 1;		if (!yaffs_ValidateTags(tags)) {			T(YAFFS_TRACE_ERROR,			  (TSTR("Writing uninitialised tags" TENDSTR)));			YBUG();		}		T(YAFFS_TRACE_WRITE,		  (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,		   tags->objectId, tags->chunkId));	} else {		T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));		YBUG();	}	if (dev->writeChunkWithTagsToNAND)		return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,						     tags);	else		return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,								       chunkInNAND,								       buffer,								       tags);}static Y_INLINE int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo){	blockNo -= dev->blockOffset;	if (dev->markNANDBlockBad)		return dev->markNANDBlockBad(dev, blockNo);	else		return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);}static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device * dev,						 int blockNo,						 yaffs_BlockState * state,						 unsigned *sequenceNumber){	blockNo -= dev->blockOffset;	if (dev->queryNANDBlock)		return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber);	else		return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,							     state,							     sequenceNumber);}static int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,				  int blockInNAND){	int result;	blockInNAND -= dev->blockOffset;	dev->nBlockErasures++;	result = dev->eraseBlockInNAND(dev, blockInNAND);	/* If at first we don't succeed, try again *once*.*/	if (!result)		result = dev->eraseBlockInNAND(dev, blockInNAND);		return result;}static int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev){	return dev->initialiseNAND(dev);}/*  * Temporary buffer manipulations. */static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo){	int i, j;	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {		if (dev->tempBuffer[i].line == 0) {			dev->tempBuffer[i].line = lineNo;			if ((i + 1) > dev->maxTemp) {				dev->maxTemp = i + 1;				for (j = 0; j <= i; j++)					dev->tempBuffer[j].maxLine =					    dev->tempBuffer[j].line;			}			return dev->tempBuffer[i].buffer;		}	}	T(YAFFS_TRACE_BUFFERS,	  (TSTR("Out of temp buffers at line %d, other held by lines:"),	   lineNo));	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {		T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line));	}	T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR)));	/*	 * If we got here then we have to allocate an unmanaged one	 * This is not good.	 */	dev->unmanagedTempAllocations++;	return YMALLOC(dev->nBytesPerChunk);}static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,				    int lineNo){	int i;	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {		if (dev->tempBuffer[i].buffer == buffer) {			dev->tempBuffer[i].line = 0;			return;		}	}	if (buffer) {		/* assume it is an unmanaged one. */		T(YAFFS_TRACE_BUFFERS,		  (TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),		   lineNo));		YFREE(buffer);		dev->unmanagedTempDeallocations++;	}}/* * Chunk bitmap manipulations */static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk){	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {		T(YAFFS_TRACE_ERROR,		  (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),		   blk));		YBUG();	}	return dev->chunkBits +	    (dev->chunkBitmapStride * (blk - dev->internalStartBlock));}static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk){	__u8 *blkBits = yaffs_BlockBits(dev, blk);	memset(blkBits, 0, dev->chunkBitmapStride);}static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk){	__u8 *blkBits = yaffs_BlockBits(dev, blk);	blkBits[chunk / 8] &= ~(1 << (chunk & 7));}static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk){	__u8 *blkBits = yaffs_BlockBits(dev, blk);	blkBits[chunk / 8] |= (1 << (chunk & 7));}static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk){	__u8 *blkBits = yaffs_BlockBits(dev, blk);	return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;}static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk){	__u8 *blkBits = yaffs_BlockBits(dev, blk);	int i;	for (i = 0; i < dev->chunkBitmapStride; i++) {		if (*blkBits)			return 1;		blkBits++;	}	return 0;}/* *  Simple hash function. Needs to have a reasonable spread */ static Y_INLINE int yaffs_HashFunction(int n){	return (n % YAFFS_NOBJECT_BUCKETS);}/* * Access functions to useful fake objects */ 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;	yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);	if (!yaffs_CheckFF(data, dev->nBytesPerChunk) || 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 chunk;	int writeOk = 1;	int attempts = 0;	do {		chunk = yaffs_AllocateChunk(dev, useReserve);		if (chunk >= 0) {			/* First check this chunk is erased... */#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK			writeOk = yaffs_CheckChunkErased(dev, chunk);#endif			if (!writeOk) {				T(YAFFS_TRACE_ERROR,				  (TSTR				   ("**>> yaffs chunk %d was not erased"				    TENDSTR), chunk));			} else {				writeOk =				    yaffs_WriteChunkWithTagsToNAND(dev, chunk,								   data, tags);			}			attempts++;			if (writeOk) {				/*				 *  Copy the data into the robustification buffer.				 *  NB We do this at the end to prevent duplicates in the case of a write error.				 *  Todo				 */				yaffs_HandleWriteChunkOk(dev, chunk, data,							 tags);			} else {				yaffs_HandleWriteChunkError(dev, chunk);			}		}	} while (chunk >= 0 && !writeOk);	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_MarkBlockBad(dev, blockInNAND);	yaffs_GetBlockInfo(dev, blockInNAND)->blockState =	    YAFFS_BLOCK_STATE_DEAD;	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){}static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND){	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;	/* Mark the block for retirement */	yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;	/* Delete the chunk */	yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);}/*---------------- Name handling functions ------------*/ static __u16 yaffs_CalcNameSum(const YCHAR * name){	__u16 sum = 0;	__u16 i = 1;	YUCHAR *bname = (YUCHAR *) name;	if (bname) {		while ((*bname) && (i <= YAFFS_MAX_NAME_LENGTH)) {#ifdef CONFIG_YAFFS_CASE_INSENSITIVE			sum += yaffs_toupper(*bname) * i;#else			sum += (*bname) * i;#endif			i++;			bname++;		}	}	return sum;}static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name){#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM	if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {		yaffs_strcpy(obj->shortName, name);	} else {		obj->shortName[0] = _Y('\0');	}#endif	obj->sum = yaffs_CalcNameSum(name);}/*-------------------- TNODES ------------------- * List of spare tnodes * The list is hooked together using the first pointer * in the tnode. */ /* yaffs_CreateTnodes creates a bunch more tnodes and * adds them to the tnode free list. * Don't use this function directly */static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes){	int i;	int tnodeSize;	yaffs_Tnode *newTnodes;	__u8 *mem;	yaffs_Tnode *curr;

⌨️ 快捷键说明

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