X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.h;h=3c7358316aba87ffa7140402f8cbba8c4baa5848;hp=de0627e273a6579def2b1deaae816e0726ea5e38;hb=49942b13d7cfbdba72c18de0f37d16d81b4372a8;hpb=4cbec5e5fa796025d6aadc2a13d79f9a00b4fbaa diff --git a/yaffs_guts.h b/yaffs_guts.h index de0627e..3c73583 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -1,8 +1,7 @@ /* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * yaffs_guts.h: Configuration etc for yaffs_guts + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. * - * Copyright (C) 2002 Aleph One Ltd. + * Copyright (C) 2002-2007 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning @@ -11,10 +10,7 @@ * it under the terms of the GNU Lesser General Public License version 2.1 as * published by the Free Software Foundation. * - * * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - * - * $Id: yaffs_guts.h,v 1.22 2006-05-17 09:31:06 charles Exp $ */ #ifndef __YAFFS_GUTS_H__ @@ -67,7 +63,7 @@ #define YAFFS_OBJECT_SPACE 0x40000 -#define YAFFS_NCHECKPOINT_OBJECTS 5000 +#define YAFFS_CHECKPOINT_VERSION 3 #ifdef CONFIG_YAFFS_UNICODE #define YAFFS_MAX_NAME_LENGTH 127 @@ -94,7 +90,13 @@ #define YAFFS_MAX_SHORT_OP_CACHES 20 -#define YAFFS_N_TEMP_BUFFERS 4 +#define YAFFS_N_TEMP_BUFFERS 6 + +/* We limit the number attempts at sucessfully saving a chunk of data. + * Small-page devices have 32 pages per block; large-page devices have 64. + * Default to something in the order of 5 to 10 blocks worth of chunks. + */ +#define YAFFS_WR_ATTEMPTS (5*64) /* Sequence numbers are used in YAFFS2 to determine block allocation order. * The range is limited slightly to help distinguish bad numbers from good. @@ -130,12 +132,12 @@ typedef struct { #ifndef CONFIG_YAFFS_NO_YAFFS1 typedef struct { - unsigned chunkId:20; - unsigned serialNumber:2; - unsigned byteCount:10; - unsigned objectId:18; - unsigned ecc:12; - unsigned unusedStuff:2; + unsigned chunkId:20; + unsigned serialNumber:2; + unsigned byteCountLSB:10; + unsigned objectId:18; + unsigned ecc:12; + unsigned byteCountMSB:2; } yaffs_Tags; @@ -164,6 +166,8 @@ typedef enum { YAFFS_OBJECT_TYPE_SPECIAL } yaffs_ObjectType; +#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL + typedef struct { unsigned validMarker0; @@ -266,13 +270,21 @@ typedef enum { /* This block has failed and is not in use */ } yaffs_BlockState; +#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) + + typedef struct { - int softDeletions:12; /* number of soft deleted pages */ - int pagesInUse:12; /* number of pages in use */ - yaffs_BlockState blockState:4; /* One of the above block states */ + int softDeletions:10; /* number of soft deleted pages */ + int pagesInUse:10; /* number of pages in use */ + unsigned blockState:4; /* One of the above block states. NB use unsigned because enum is sometimes an int */ __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */ /* and retire the block. */ + __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */ + __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block. + It should be prioritised for GC */ + __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ + #ifdef CONFIG_YAFFS_YAFFS2 __u32 hasShrinkHeader:1; /* This block has at least one shrink object header */ __u32 sequenceNumber; /* block sequence number for yaffs2 */ @@ -288,11 +300,11 @@ typedef struct { /* Apply to everything */ int parentObjectId; - __u16 sum__NoLongerUsed; /* checksum of name. No longer used */ - YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; + __u16 sum__NoLongerUsed; /* checksum of name. No longer used */ + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; - /* Thes following apply to directories, files, symlinks - not hard links */ - __u32 yst_mode; /* protection */ + /* The following apply to directories, files, symlinks - not hard links */ + __u32 yst_mode; /* protection */ #ifdef CONFIG_YAFFS_WINCE __u32 notForWinCE[5]; @@ -319,11 +331,14 @@ typedef struct { __u32 win_ctime[2]; __u32 win_atime[2]; __u32 win_mtime[2]; - __u32 roomToGrow[4]; #else - __u32 roomToGrow[10]; + __u32 roomToGrow[6]; + #endif + __u32 inbandShadowsObject; + __u32 inbandIsShrink; + __u32 reservedSpace[2]; int shadowsObject; /* This object header shadows the specified object if > 0 */ /* isShrink applies to object headers written when we shrink the file (ie resize) */ @@ -369,7 +384,7 @@ typedef struct { } yaffs_FileStructure; typedef struct { - struct list_head children; /* list of child links */ + struct ylist_head children; /* list of child links */ } yaffs_DirectoryStructure; typedef struct { @@ -405,33 +420,35 @@ struct yaffs_ObjectStruct { __u8 deferedFree:1; /* For Linux kernel. Object is removed from NAND, but is * still in the inode cache. Free of object is defered. * until the inode is released. - */ + */ - __u8 serial; /* serial number of chunk in NAND. Cached here */ - __u16 sum; /* sum of the name to speed searching */ + __u8 serial; /* serial number of chunk in NAND. Cached here */ +/* __u16 sum_prev; */ + __u16 sum; /* sum of the name to speed searching */ +/* __u16 sum_trailer; */ - struct yaffs_DeviceStruct *myDev; /* The device I'm on */ + struct yaffs_DeviceStruct *myDev; /* The device I'm on */ - struct list_head hashLink; /* list of objects in this hash bucket */ + struct ylist_head hashLink; /* list of objects in this hash bucket */ - struct list_head hardLinks; /* all the equivalent hard linked objects */ + struct ylist_head hardLinks; /* all the equivalent hard linked objects */ - /* directory structure stuff */ - /* also used for linking up the free list */ - struct yaffs_ObjectStruct *parent; - struct list_head siblings; + /* directory structure stuff */ + /* also used for linking up the free list */ + struct yaffs_ObjectStruct *parent; + struct ylist_head siblings; /* Where's my object header in NAND? */ - int chunkId; + int hdrChunk; int nDataChunks; /* Number of data chunks attached to the file. */ __u32 objectId; /* the object id value */ - __u32 yst_mode; + __u32 yst_mode; #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM - YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1]; + YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1]; #endif #ifndef __KERNEL__ @@ -473,8 +490,8 @@ struct yaffs_ObjectList_struct { typedef struct yaffs_ObjectList_struct yaffs_ObjectList; typedef struct { - struct list_head list; - int count; + struct ylist_head list; + int count; } yaffs_ObjectBucket; @@ -486,8 +503,7 @@ typedef struct { int structType; __u32 objectId; __u32 parentId; - int chunkId; - + int hdrChunk; yaffs_ObjectType variantType:3; __u8 deleted:1; __u8 softDeleted:1; @@ -516,26 +532,23 @@ typedef struct { /*----------------- Device ---------------------------------*/ struct yaffs_DeviceStruct { - struct list_head devList; - const char *name; - - /* Entry parameters set up way early. Yaffs sets up the rest.*/ - int nBytesPerChunk; /* Should be a power of 2 >= 512 */ - int nChunksPerBlock; /* does not need to be a power of 2 */ - int nBytesPerSpare; /* spare area size */ - int startBlock; /* Start block we're allowed to use */ - int endBlock; /* End block we're allowed to use */ - int nReservedBlocks; /* We want this tuneable so that we can reduce */ + struct ylist_head devList; + const char *name; + + /* Entry parameters set up way early. Yaffs sets up the rest.*/ + int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */ + int nChunksPerBlock; /* does not need to be a power of 2 */ + int spareBytesPerChunk;/* spare area size */ + int startBlock; /* Start block we're allowed to use */ + int endBlock; /* End block we're allowed to use */ + int nReservedBlocks; /* We want this tuneable so that we can reduce */ /* reserved blocks on NOR and RAM. */ - /* Stuff used by the partitioned checkpointing mechanism */ - int checkpointStartBlock; - int checkpointEndBlock; /* Stuff used by the shared space checkpointing mechanism */ /* If this value is zero, then this mechanism is disabled */ - int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ +// int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ @@ -561,12 +574,13 @@ struct yaffs_DeviceStruct { int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev, int chunkInNAND, __u8 * data, yaffs_Spare * spare); - int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, - int blockInNAND); - int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); + int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, + int blockInNAND); + int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); + int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev); #ifdef CONFIG_YAFFS_YAFFS2 - int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, + int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * tags); int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev, @@ -574,7 +588,7 @@ struct yaffs_DeviceStruct { yaffs_ExtendedTags * tags); int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo); int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo, - yaffs_BlockState * state, int *sequenceNumber); + yaffs_BlockState * state, __u32 *sequenceNumber); #endif int isYaffs2; @@ -590,8 +604,14 @@ struct yaffs_DeviceStruct { int wideTnodesDisabled; /* Set to disable wide tnodes */ + YCHAR *pathDividers; /* String of legal path dividers */ + /* End of stuff that must be set before initialisation. */ + + /* Checkpoint control. Can be set before or after initialisation */ + __u8 skipCheckpointRead; + __u8 skipCheckpointWrite; /* Runtime parameters. Set up by YAFFS. */ @@ -602,6 +622,14 @@ struct yaffs_DeviceStruct { __u32 tnodeWidth; __u32 tnodeMask; + /* Stuff for figuring out file offset to chunk conversions */ + __u32 chunkShift; /* Shift value */ + __u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */ + __u32 chunkMask; /* Mask to use for power-of-2 case */ + + /* Stuff to handle inband tags */ + int inbandTags; + __u32 totalBytesPerChunk; #ifdef __KERNEL__ @@ -617,6 +645,7 @@ struct yaffs_DeviceStruct { int isCheckpointed; + /* Stuff to support block offsetting to support start block zero */ int internalStartBlock; int internalEndBlock; @@ -636,6 +665,10 @@ struct yaffs_DeviceStruct { int checkpointNextBlock; int *checkpointBlockList; int checkpointMaxBlocks; + __u32 checkpointSum; + __u32 checkpointXor; + + int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */ /* Block Info */ yaffs_BlockInfo *blockInfo; @@ -662,6 +695,8 @@ struct yaffs_DeviceStruct { int nObjectsCreated; yaffs_Object *freeObjects; int nFreeObjects; + + int nHardLinks; yaffs_ObjectList *allocatedObjectList; @@ -672,6 +707,7 @@ struct yaffs_DeviceStruct { int currentDirtyChecker; /* Used to find current dirtiest block */ __u32 *gcCleanupList; /* objects to delete at the end of a GC. */ + int nonAggressiveSkip; /* GC state/mode */ /* Statistcs */ int nPageWrites; @@ -689,6 +725,8 @@ struct yaffs_DeviceStruct { int tagsEccUnfixed; int nDeletions; int nUnmarkedDeletions; + + int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */ /* Special directories */ yaffs_Object *rootDir; @@ -715,9 +753,11 @@ struct yaffs_DeviceStruct { int nUnlinkedFiles; /* Count of unlinked files. */ int nBackgroundDeletions; /* Count of background deletions. */ - + + /* Temporary buffer management */ yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS]; int maxTemp; + int tempInUse; int unmanagedTempAllocations; int unmanagedTempDeallocations; @@ -729,10 +769,10 @@ struct yaffs_DeviceStruct { typedef struct yaffs_DeviceStruct yaffs_Device; -/* The static layout of bllock usage etc is stored in the super block header */ +/* The static layout of block usage etc is stored in the super block header */ typedef struct { int StructType; - int version; + int version; int checkpointStartBlock; int checkpointEndBlock; int startBlock; @@ -768,18 +808,6 @@ typedef struct { __u32 head; } yaffs_CheckpointValidity; -/* Function to manipulate block info */ -static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) -{ - if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { - T(YAFFS_TRACE_ERROR, - (TSTR - ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), - blk)); - YBUG(); - } - return &dev->blockInfo[blk - dev->internalStartBlock]; -} /*----------------------- YAFFS Functions -----------------------*/ @@ -804,14 +832,14 @@ int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr); int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr); /* File operations */ -int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, __u32 offset, - int nBytes); -int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, __u32 offset, - int nBytes, int writeThrough); -int yaffs_ResizeFile(yaffs_Object * obj, int newSize); +int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset, + int nBytes); +int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset, + int nBytes, int writeThrough); +int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize); yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, - __u32 mode, __u32 uid, __u32 gid); + __u32 mode, __u32 uid, __u32 gid); int yaffs_FlushFile(yaffs_Object * obj, int updateTime); /* Flushing and checkpointing */ @@ -868,5 +896,9 @@ void yaffs_GutsTest(yaffs_Device * dev); void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn); int yaffs_CheckFF(__u8 * buffer, int nBytes); +void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi); + +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo); +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo); #endif