X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_guts.h;h=3c7358316aba87ffa7140402f8cbba8c4baa5848;hp=aaeda26e1c29703f36dee9560b0d647c0a890766;hb=49942b13d7cfbdba72c18de0f37d16d81b4372a8;hpb=751cba724040d777d1768dd5d4997039962d2608 diff --git a/yaffs_guts.h b/yaffs_guts.h index aaeda26..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.20 2006-03-08 07:59:20 charles Exp $ */ #ifndef __YAFFS_GUTS_H__ @@ -64,8 +60,11 @@ #define YAFFS_NOBJECT_BUCKETS 256 + #define YAFFS_OBJECT_SPACE 0x40000 +#define YAFFS_CHECKPOINT_VERSION 3 + #ifdef CONFIG_YAFFS_UNICODE #define YAFFS_MAX_NAME_LENGTH 127 #define YAFFS_MAX_ALIAS_LENGTH 79 @@ -76,15 +75,28 @@ #define YAFFS_SHORT_NAME_LENGTH 15 -/* Some special object ids */ +/* Some special object ids for pseudo objects */ #define YAFFS_OBJECTID_ROOT 1 #define YAFFS_OBJECTID_LOSTNFOUND 2 #define YAFFS_OBJECTID_UNLINKED 3 #define YAFFS_OBJECTID_DELETED 4 +/* Sseudo object ids for checkpointing */ +#define YAFFS_OBJECTID_SB_HEADER 0x10 +#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20 +#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21 + +/* */ + #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. @@ -120,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; @@ -154,6 +166,8 @@ typedef enum { YAFFS_OBJECT_TYPE_SPECIAL } yaffs_ObjectType; +#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL + typedef struct { unsigned validMarker0; @@ -231,13 +245,13 @@ typedef enum { YAFFS_BLOCK_STATE_ALLOCATING, /* This block is partially allocated. + * At least one page holds valid data. * This is the one currently being used for page * allocation. Should never be more than one of these */ YAFFS_BLOCK_STATE_FULL, /* All the pages in this block have been allocated. - * At least one page holds valid data. */ YAFFS_BLOCK_STATE_DIRTY, @@ -245,6 +259,10 @@ typedef enum { * Erase me, reuse me. */ + YAFFS_BLOCK_STATE_CHECKPOINT, + /* This block is assigned to holding checkpoint data. + */ + YAFFS_BLOCK_STATE_COLLECTING, /* This block is being garbage collected */ @@ -252,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 */ @@ -274,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]; @@ -305,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) */ @@ -355,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 { @@ -391,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__ @@ -459,10 +490,34 @@ 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; + +/* yaffs_CheckpointObject holds the definition of an object as dumped + * by checkpointing. + */ + +typedef struct { + int structType; + __u32 objectId; + __u32 parentId; + int hdrChunk; + yaffs_ObjectType variantType:3; + __u8 deleted:1; + __u8 softDeleted:1; + __u8 unlinked:1; + __u8 fake:1; + __u8 renameAllowed:1; + __u8 unlinkAllowed:1; + __u8 serial; + + int nDataChunks; + __u32 fileSizeOrEquivalentObjectId; + +}yaffs_CheckpointObject; + /*--------------------- Temporary buffers ---------------- * * These are chunk-sized working buffers. Each device has a few @@ -477,17 +532,26 @@ 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 shared space checkpointing mechanism */ + /* If this value is zero, then this mechanism is disabled */ + +// int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ + + + int nShortOpCaches; /* If <= 0, then short op caching is disabled, else * the number of short op caches (don't use too many) @@ -500,6 +564,8 @@ struct yaffs_DeviceStruct { void *genericDevice; /* Pointer to device context * On an mtd this holds the mtd pointer. */ + void *superBlock; + /* NAND access functions (Must be set before calling YAFFS)*/ int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev, @@ -508,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, @@ -521,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; @@ -532,10 +599,19 @@ struct yaffs_DeviceStruct { */ void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj); + /* Callback to mark the superblock dirsty */ + void (*markSuperBlockDirty)(void * superblock); + 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. */ @@ -546,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__ @@ -558,13 +642,34 @@ struct yaffs_DeviceStruct { #endif int isMounted; + + int isCheckpointed; + /* Stuff to support block offsetting to support start block zero */ int internalStartBlock; int internalEndBlock; int blockOffset; int chunkOffset; + + /* Runtime checkpointing stuff */ + int checkpointPageSequence; /* running sequence number of checkpoint pages */ + int checkpointByteCount; + int checkpointByteOffset; + __u8 *checkpointBuffer; + int checkpointOpenForWrite; + int blocksInCheckpoint; + int checkpointCurrentChunk; + int checkpointCurrentBlock; + 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; __u8 *chunkBits; /* bitmap of chunks in use */ @@ -590,6 +695,8 @@ struct yaffs_DeviceStruct { int nObjectsCreated; yaffs_Object *freeObjects; int nFreeObjects; + + int nHardLinks; yaffs_ObjectList *allocatedObjectList; @@ -600,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; @@ -617,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; @@ -643,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; @@ -657,26 +769,51 @@ struct yaffs_DeviceStruct { typedef struct yaffs_DeviceStruct yaffs_Device; -/* 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]; -} +/* The static layout of block usage etc is stored in the super block header */ +typedef struct { + int StructType; + int version; + int checkpointStartBlock; + int checkpointEndBlock; + int startBlock; + int endBlock; + int rfu[100]; +} yaffs_SuperBlockHeader; + +/* The CheckpointDevice structure holds the device information that changes at runtime and + * must be preserved over unmount/mount cycles. + */ +typedef struct { + int structType; + int nErasedBlocks; + int allocationBlock; /* Current block being allocated off */ + __u32 allocationPage; + int nFreeChunks; + + int nDeletedFiles; /* Count of files awaiting deletion;*/ + int nUnlinkedFiles; /* Count of unlinked files. */ + int nBackgroundDeletions; /* Count of background deletions. */ + + /* yaffs2 runtime stuff */ + unsigned sequenceNumber; /* Sequence number of currently allocating block */ + unsigned oldestDirtySequence; + +} yaffs_CheckpointDevice; + + +typedef struct { + int structType; + __u32 magic; + __u32 version; + __u32 head; +} yaffs_CheckpointValidity; + /*----------------------- YAFFS Functions -----------------------*/ int yaffs_GutsInitialise(yaffs_Device * dev); void yaffs_Deinitialise(yaffs_Device * dev); -void yaffs_FlushEntireDeviceCache(yaffs_Device *dev); - int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev); int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, @@ -695,16 +832,22 @@ 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 */ +void yaffs_FlushEntireDeviceCache(yaffs_Device *dev); + +int yaffs_CheckpointSave(yaffs_Device *dev); +int yaffs_CheckpointRestore(yaffs_Device *dev); + /* Directory operations */ yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, __u32 mode, __u32 uid, __u32 gid); @@ -753,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