1*0e8cc8bdSWilliam Juul /* 2*0e8cc8bdSWilliam Juul * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 3*0e8cc8bdSWilliam Juul * 4*0e8cc8bdSWilliam Juul * Copyright (C) 2002-2007 Aleph One Ltd. 5*0e8cc8bdSWilliam Juul * for Toby Churchill Ltd and Brightstar Engineering 6*0e8cc8bdSWilliam Juul * 7*0e8cc8bdSWilliam Juul * Created by Charles Manning <charles@aleph1.co.uk> 8*0e8cc8bdSWilliam Juul * 9*0e8cc8bdSWilliam Juul * This program is free software; you can redistribute it and/or modify 10*0e8cc8bdSWilliam Juul * it under the terms of the GNU Lesser General Public License version 2.1 as 11*0e8cc8bdSWilliam Juul * published by the Free Software Foundation. 12*0e8cc8bdSWilliam Juul * 13*0e8cc8bdSWilliam Juul * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. 14*0e8cc8bdSWilliam Juul */ 15*0e8cc8bdSWilliam Juul 16*0e8cc8bdSWilliam Juul #ifndef __YAFFS_GUTS_H__ 17*0e8cc8bdSWilliam Juul #define __YAFFS_GUTS_H__ 18*0e8cc8bdSWilliam Juul 19*0e8cc8bdSWilliam Juul #include "devextras.h" 20*0e8cc8bdSWilliam Juul #include "yportenv.h" 21*0e8cc8bdSWilliam Juul 22*0e8cc8bdSWilliam Juul #define YAFFS_OK 1 23*0e8cc8bdSWilliam Juul #define YAFFS_FAIL 0 24*0e8cc8bdSWilliam Juul 25*0e8cc8bdSWilliam Juul /* Give us a Y=0x59, 26*0e8cc8bdSWilliam Juul * Give us an A=0x41, 27*0e8cc8bdSWilliam Juul * Give us an FF=0xFF 28*0e8cc8bdSWilliam Juul * Give us an S=0x53 29*0e8cc8bdSWilliam Juul * And what have we got... 30*0e8cc8bdSWilliam Juul */ 31*0e8cc8bdSWilliam Juul #define YAFFS_MAGIC 0x5941FF53 32*0e8cc8bdSWilliam Juul 33*0e8cc8bdSWilliam Juul #define YAFFS_NTNODES_LEVEL0 16 34*0e8cc8bdSWilliam Juul #define YAFFS_TNODES_LEVEL0_BITS 4 35*0e8cc8bdSWilliam Juul #define YAFFS_TNODES_LEVEL0_MASK 0xf 36*0e8cc8bdSWilliam Juul 37*0e8cc8bdSWilliam Juul #define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) 38*0e8cc8bdSWilliam Juul #define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) 39*0e8cc8bdSWilliam Juul #define YAFFS_TNODES_INTERNAL_MASK 0x7 40*0e8cc8bdSWilliam Juul #define YAFFS_TNODES_MAX_LEVEL 6 41*0e8cc8bdSWilliam Juul 42*0e8cc8bdSWilliam Juul #ifndef CONFIG_YAFFS_NO_YAFFS1 43*0e8cc8bdSWilliam Juul #define YAFFS_BYTES_PER_SPARE 16 44*0e8cc8bdSWilliam Juul #define YAFFS_BYTES_PER_CHUNK 512 45*0e8cc8bdSWilliam Juul #define YAFFS_CHUNK_SIZE_SHIFT 9 46*0e8cc8bdSWilliam Juul #define YAFFS_CHUNKS_PER_BLOCK 32 47*0e8cc8bdSWilliam Juul #define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) 48*0e8cc8bdSWilliam Juul #endif 49*0e8cc8bdSWilliam Juul 50*0e8cc8bdSWilliam Juul #define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024 51*0e8cc8bdSWilliam Juul #define YAFFS_MIN_YAFFS2_SPARE_SIZE 32 52*0e8cc8bdSWilliam Juul 53*0e8cc8bdSWilliam Juul #define YAFFS_MAX_CHUNK_ID 0x000FFFFF 54*0e8cc8bdSWilliam Juul 55*0e8cc8bdSWilliam Juul #define YAFFS_UNUSED_OBJECT_ID 0x0003FFFF 56*0e8cc8bdSWilliam Juul 57*0e8cc8bdSWilliam Juul #define YAFFS_ALLOCATION_NOBJECTS 100 58*0e8cc8bdSWilliam Juul #define YAFFS_ALLOCATION_NTNODES 100 59*0e8cc8bdSWilliam Juul #define YAFFS_ALLOCATION_NLINKS 100 60*0e8cc8bdSWilliam Juul 61*0e8cc8bdSWilliam Juul #define YAFFS_NOBJECT_BUCKETS 256 62*0e8cc8bdSWilliam Juul 63*0e8cc8bdSWilliam Juul 64*0e8cc8bdSWilliam Juul #define YAFFS_OBJECT_SPACE 0x40000 65*0e8cc8bdSWilliam Juul 66*0e8cc8bdSWilliam Juul #define YAFFS_CHECKPOINT_VERSION 3 67*0e8cc8bdSWilliam Juul 68*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_UNICODE 69*0e8cc8bdSWilliam Juul #define YAFFS_MAX_NAME_LENGTH 127 70*0e8cc8bdSWilliam Juul #define YAFFS_MAX_ALIAS_LENGTH 79 71*0e8cc8bdSWilliam Juul #else 72*0e8cc8bdSWilliam Juul #define YAFFS_MAX_NAME_LENGTH 255 73*0e8cc8bdSWilliam Juul #define YAFFS_MAX_ALIAS_LENGTH 159 74*0e8cc8bdSWilliam Juul #endif 75*0e8cc8bdSWilliam Juul 76*0e8cc8bdSWilliam Juul #define YAFFS_SHORT_NAME_LENGTH 15 77*0e8cc8bdSWilliam Juul 78*0e8cc8bdSWilliam Juul /* Some special object ids for pseudo objects */ 79*0e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_ROOT 1 80*0e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_LOSTNFOUND 2 81*0e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_UNLINKED 3 82*0e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_DELETED 4 83*0e8cc8bdSWilliam Juul 84*0e8cc8bdSWilliam Juul /* Sseudo object ids for checkpointing */ 85*0e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_SB_HEADER 0x10 86*0e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20 87*0e8cc8bdSWilliam Juul #define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21 88*0e8cc8bdSWilliam Juul 89*0e8cc8bdSWilliam Juul /* */ 90*0e8cc8bdSWilliam Juul 91*0e8cc8bdSWilliam Juul #define YAFFS_MAX_SHORT_OP_CACHES 20 92*0e8cc8bdSWilliam Juul 93*0e8cc8bdSWilliam Juul #define YAFFS_N_TEMP_BUFFERS 4 94*0e8cc8bdSWilliam Juul 95*0e8cc8bdSWilliam Juul /* We limit the number attempts at sucessfully saving a chunk of data. 96*0e8cc8bdSWilliam Juul * Small-page devices have 32 pages per block; large-page devices have 64. 97*0e8cc8bdSWilliam Juul * Default to something in the order of 5 to 10 blocks worth of chunks. 98*0e8cc8bdSWilliam Juul */ 99*0e8cc8bdSWilliam Juul #define YAFFS_WR_ATTEMPTS (5*64) 100*0e8cc8bdSWilliam Juul 101*0e8cc8bdSWilliam Juul /* Sequence numbers are used in YAFFS2 to determine block allocation order. 102*0e8cc8bdSWilliam Juul * The range is limited slightly to help distinguish bad numbers from good. 103*0e8cc8bdSWilliam Juul * This also allows us to perhaps in the future use special numbers for 104*0e8cc8bdSWilliam Juul * special purposes. 105*0e8cc8bdSWilliam Juul * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, 106*0e8cc8bdSWilliam Juul * and is a larger number than the lifetime of a 2GB device. 107*0e8cc8bdSWilliam Juul */ 108*0e8cc8bdSWilliam Juul #define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 109*0e8cc8bdSWilliam Juul #define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xEFFFFF00 110*0e8cc8bdSWilliam Juul 111*0e8cc8bdSWilliam Juul /* ChunkCache is used for short read/write operations.*/ 112*0e8cc8bdSWilliam Juul typedef struct { 113*0e8cc8bdSWilliam Juul struct yaffs_ObjectStruct *object; 114*0e8cc8bdSWilliam Juul int chunkId; 115*0e8cc8bdSWilliam Juul int lastUse; 116*0e8cc8bdSWilliam Juul int dirty; 117*0e8cc8bdSWilliam Juul int nBytes; /* Only valid if the cache is dirty */ 118*0e8cc8bdSWilliam Juul int locked; /* Can't push out or flush while locked. */ 119*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_YAFFS2 120*0e8cc8bdSWilliam Juul __u8 *data; 121*0e8cc8bdSWilliam Juul #else 122*0e8cc8bdSWilliam Juul __u8 data[YAFFS_BYTES_PER_CHUNK]; 123*0e8cc8bdSWilliam Juul #endif 124*0e8cc8bdSWilliam Juul } yaffs_ChunkCache; 125*0e8cc8bdSWilliam Juul 126*0e8cc8bdSWilliam Juul 127*0e8cc8bdSWilliam Juul 128*0e8cc8bdSWilliam Juul /* Tags structures in RAM 129*0e8cc8bdSWilliam Juul * NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise 130*0e8cc8bdSWilliam Juul * the structure size will get blown out. 131*0e8cc8bdSWilliam Juul */ 132*0e8cc8bdSWilliam Juul 133*0e8cc8bdSWilliam Juul #ifndef CONFIG_YAFFS_NO_YAFFS1 134*0e8cc8bdSWilliam Juul typedef struct { 135*0e8cc8bdSWilliam Juul unsigned chunkId:20; 136*0e8cc8bdSWilliam Juul unsigned serialNumber:2; 137*0e8cc8bdSWilliam Juul unsigned byteCount:10; 138*0e8cc8bdSWilliam Juul unsigned objectId:18; 139*0e8cc8bdSWilliam Juul unsigned ecc:12; 140*0e8cc8bdSWilliam Juul unsigned unusedStuff:2; 141*0e8cc8bdSWilliam Juul 142*0e8cc8bdSWilliam Juul } yaffs_Tags; 143*0e8cc8bdSWilliam Juul 144*0e8cc8bdSWilliam Juul typedef union { 145*0e8cc8bdSWilliam Juul yaffs_Tags asTags; 146*0e8cc8bdSWilliam Juul __u8 asBytes[8]; 147*0e8cc8bdSWilliam Juul } yaffs_TagsUnion; 148*0e8cc8bdSWilliam Juul 149*0e8cc8bdSWilliam Juul #endif 150*0e8cc8bdSWilliam Juul 151*0e8cc8bdSWilliam Juul /* Stuff used for extended tags in YAFFS2 */ 152*0e8cc8bdSWilliam Juul 153*0e8cc8bdSWilliam Juul typedef enum { 154*0e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_UNKNOWN, 155*0e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_NO_ERROR, 156*0e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_FIXED, 157*0e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_UNFIXED 158*0e8cc8bdSWilliam Juul } yaffs_ECCResult; 159*0e8cc8bdSWilliam Juul 160*0e8cc8bdSWilliam Juul typedef enum { 161*0e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_UNKNOWN, 162*0e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_FILE, 163*0e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_SYMLINK, 164*0e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_DIRECTORY, 165*0e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_HARDLINK, 166*0e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_SPECIAL 167*0e8cc8bdSWilliam Juul } yaffs_ObjectType; 168*0e8cc8bdSWilliam Juul 169*0e8cc8bdSWilliam Juul #define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL 170*0e8cc8bdSWilliam Juul 171*0e8cc8bdSWilliam Juul typedef struct { 172*0e8cc8bdSWilliam Juul 173*0e8cc8bdSWilliam Juul unsigned validMarker0; 174*0e8cc8bdSWilliam Juul unsigned chunkUsed; /* Status of the chunk: used or unused */ 175*0e8cc8bdSWilliam Juul unsigned objectId; /* If 0 then this is not part of an object (unused) */ 176*0e8cc8bdSWilliam Juul unsigned chunkId; /* If 0 then this is a header, else a data chunk */ 177*0e8cc8bdSWilliam Juul unsigned byteCount; /* Only valid for data chunks */ 178*0e8cc8bdSWilliam Juul 179*0e8cc8bdSWilliam Juul /* The following stuff only has meaning when we read */ 180*0e8cc8bdSWilliam Juul yaffs_ECCResult eccResult; 181*0e8cc8bdSWilliam Juul unsigned blockBad; 182*0e8cc8bdSWilliam Juul 183*0e8cc8bdSWilliam Juul /* YAFFS 1 stuff */ 184*0e8cc8bdSWilliam Juul unsigned chunkDeleted; /* The chunk is marked deleted */ 185*0e8cc8bdSWilliam Juul unsigned serialNumber; /* Yaffs1 2-bit serial number */ 186*0e8cc8bdSWilliam Juul 187*0e8cc8bdSWilliam Juul /* YAFFS2 stuff */ 188*0e8cc8bdSWilliam Juul unsigned sequenceNumber; /* The sequence number of this block */ 189*0e8cc8bdSWilliam Juul 190*0e8cc8bdSWilliam Juul /* Extra info if this is an object header (YAFFS2 only) */ 191*0e8cc8bdSWilliam Juul 192*0e8cc8bdSWilliam Juul unsigned extraHeaderInfoAvailable; /* There is extra info available if this is not zero */ 193*0e8cc8bdSWilliam Juul unsigned extraParentObjectId; /* The parent object */ 194*0e8cc8bdSWilliam Juul unsigned extraIsShrinkHeader; /* Is it a shrink header? */ 195*0e8cc8bdSWilliam Juul unsigned extraShadows; /* Does this shadow another object? */ 196*0e8cc8bdSWilliam Juul 197*0e8cc8bdSWilliam Juul yaffs_ObjectType extraObjectType; /* What object type? */ 198*0e8cc8bdSWilliam Juul 199*0e8cc8bdSWilliam Juul unsigned extraFileLength; /* Length if it is a file */ 200*0e8cc8bdSWilliam Juul unsigned extraEquivalentObjectId; /* Equivalent object Id if it is a hard link */ 201*0e8cc8bdSWilliam Juul 202*0e8cc8bdSWilliam Juul unsigned validMarker1; 203*0e8cc8bdSWilliam Juul 204*0e8cc8bdSWilliam Juul } yaffs_ExtendedTags; 205*0e8cc8bdSWilliam Juul 206*0e8cc8bdSWilliam Juul /* Spare structure for YAFFS1 */ 207*0e8cc8bdSWilliam Juul typedef struct { 208*0e8cc8bdSWilliam Juul __u8 tagByte0; 209*0e8cc8bdSWilliam Juul __u8 tagByte1; 210*0e8cc8bdSWilliam Juul __u8 tagByte2; 211*0e8cc8bdSWilliam Juul __u8 tagByte3; 212*0e8cc8bdSWilliam Juul __u8 pageStatus; /* set to 0 to delete the chunk */ 213*0e8cc8bdSWilliam Juul __u8 blockStatus; 214*0e8cc8bdSWilliam Juul __u8 tagByte4; 215*0e8cc8bdSWilliam Juul __u8 tagByte5; 216*0e8cc8bdSWilliam Juul __u8 ecc1[3]; 217*0e8cc8bdSWilliam Juul __u8 tagByte6; 218*0e8cc8bdSWilliam Juul __u8 tagByte7; 219*0e8cc8bdSWilliam Juul __u8 ecc2[3]; 220*0e8cc8bdSWilliam Juul } yaffs_Spare; 221*0e8cc8bdSWilliam Juul 222*0e8cc8bdSWilliam Juul /*Special structure for passing through to mtd */ 223*0e8cc8bdSWilliam Juul struct yaffs_NANDSpare { 224*0e8cc8bdSWilliam Juul yaffs_Spare spare; 225*0e8cc8bdSWilliam Juul int eccres1; 226*0e8cc8bdSWilliam Juul int eccres2; 227*0e8cc8bdSWilliam Juul }; 228*0e8cc8bdSWilliam Juul 229*0e8cc8bdSWilliam Juul /* Block data in RAM */ 230*0e8cc8bdSWilliam Juul 231*0e8cc8bdSWilliam Juul typedef enum { 232*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_UNKNOWN = 0, 233*0e8cc8bdSWilliam Juul 234*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_SCANNING, 235*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_NEEDS_SCANNING, 236*0e8cc8bdSWilliam Juul /* The block might have something on it (ie it is allocating or full, perhaps empty) 237*0e8cc8bdSWilliam Juul * but it needs to be scanned to determine its true state. 238*0e8cc8bdSWilliam Juul * This state is only valid during yaffs_Scan. 239*0e8cc8bdSWilliam Juul * NB We tolerate empty because the pre-scanner might be incapable of deciding 240*0e8cc8bdSWilliam Juul * However, if this state is returned on a YAFFS2 device, then we expect a sequence number 241*0e8cc8bdSWilliam Juul */ 242*0e8cc8bdSWilliam Juul 243*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_EMPTY, 244*0e8cc8bdSWilliam Juul /* This block is empty */ 245*0e8cc8bdSWilliam Juul 246*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_ALLOCATING, 247*0e8cc8bdSWilliam Juul /* This block is partially allocated. 248*0e8cc8bdSWilliam Juul * At least one page holds valid data. 249*0e8cc8bdSWilliam Juul * This is the one currently being used for page 250*0e8cc8bdSWilliam Juul * allocation. Should never be more than one of these 251*0e8cc8bdSWilliam Juul */ 252*0e8cc8bdSWilliam Juul 253*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_FULL, 254*0e8cc8bdSWilliam Juul /* All the pages in this block have been allocated. 255*0e8cc8bdSWilliam Juul */ 256*0e8cc8bdSWilliam Juul 257*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_DIRTY, 258*0e8cc8bdSWilliam Juul /* All pages have been allocated and deleted. 259*0e8cc8bdSWilliam Juul * Erase me, reuse me. 260*0e8cc8bdSWilliam Juul */ 261*0e8cc8bdSWilliam Juul 262*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_CHECKPOINT, 263*0e8cc8bdSWilliam Juul /* This block is assigned to holding checkpoint data. 264*0e8cc8bdSWilliam Juul */ 265*0e8cc8bdSWilliam Juul 266*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_COLLECTING, 267*0e8cc8bdSWilliam Juul /* This block is being garbage collected */ 268*0e8cc8bdSWilliam Juul 269*0e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_DEAD 270*0e8cc8bdSWilliam Juul /* This block has failed and is not in use */ 271*0e8cc8bdSWilliam Juul } yaffs_BlockState; 272*0e8cc8bdSWilliam Juul 273*0e8cc8bdSWilliam Juul #define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) 274*0e8cc8bdSWilliam Juul 275*0e8cc8bdSWilliam Juul 276*0e8cc8bdSWilliam Juul typedef struct { 277*0e8cc8bdSWilliam Juul 278*0e8cc8bdSWilliam Juul int softDeletions:10; /* number of soft deleted pages */ 279*0e8cc8bdSWilliam Juul int pagesInUse:10; /* number of pages in use */ 280*0e8cc8bdSWilliam Juul unsigned blockState:4; /* One of the above block states. NB use unsigned because enum is sometimes an int */ 281*0e8cc8bdSWilliam Juul __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */ 282*0e8cc8bdSWilliam Juul /* and retire the block. */ 283*0e8cc8bdSWilliam Juul __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */ 284*0e8cc8bdSWilliam Juul __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block. 285*0e8cc8bdSWilliam Juul It should be prioritised for GC */ 286*0e8cc8bdSWilliam Juul __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ 287*0e8cc8bdSWilliam Juul 288*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_YAFFS2 289*0e8cc8bdSWilliam Juul __u32 hasShrinkHeader:1; /* This block has at least one shrink object header */ 290*0e8cc8bdSWilliam Juul __u32 sequenceNumber; /* block sequence number for yaffs2 */ 291*0e8cc8bdSWilliam Juul #endif 292*0e8cc8bdSWilliam Juul 293*0e8cc8bdSWilliam Juul } yaffs_BlockInfo; 294*0e8cc8bdSWilliam Juul 295*0e8cc8bdSWilliam Juul /* -------------------------- Object structure -------------------------------*/ 296*0e8cc8bdSWilliam Juul /* This is the object structure as stored on NAND */ 297*0e8cc8bdSWilliam Juul 298*0e8cc8bdSWilliam Juul typedef struct { 299*0e8cc8bdSWilliam Juul yaffs_ObjectType type; 300*0e8cc8bdSWilliam Juul 301*0e8cc8bdSWilliam Juul /* Apply to everything */ 302*0e8cc8bdSWilliam Juul int parentObjectId; 303*0e8cc8bdSWilliam Juul __u16 sum__NoLongerUsed; /* checksum of name. No longer used */ 304*0e8cc8bdSWilliam Juul YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; 305*0e8cc8bdSWilliam Juul 306*0e8cc8bdSWilliam Juul /* Thes following apply to directories, files, symlinks - not hard links */ 307*0e8cc8bdSWilliam Juul __u32 yst_mode; /* protection */ 308*0e8cc8bdSWilliam Juul 309*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_WINCE 310*0e8cc8bdSWilliam Juul __u32 notForWinCE[5]; 311*0e8cc8bdSWilliam Juul #else 312*0e8cc8bdSWilliam Juul __u32 yst_uid; 313*0e8cc8bdSWilliam Juul __u32 yst_gid; 314*0e8cc8bdSWilliam Juul __u32 yst_atime; 315*0e8cc8bdSWilliam Juul __u32 yst_mtime; 316*0e8cc8bdSWilliam Juul __u32 yst_ctime; 317*0e8cc8bdSWilliam Juul #endif 318*0e8cc8bdSWilliam Juul 319*0e8cc8bdSWilliam Juul /* File size applies to files only */ 320*0e8cc8bdSWilliam Juul int fileSize; 321*0e8cc8bdSWilliam Juul 322*0e8cc8bdSWilliam Juul /* Equivalent object id applies to hard links only. */ 323*0e8cc8bdSWilliam Juul int equivalentObjectId; 324*0e8cc8bdSWilliam Juul 325*0e8cc8bdSWilliam Juul /* Alias is for symlinks only. */ 326*0e8cc8bdSWilliam Juul YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1]; 327*0e8cc8bdSWilliam Juul 328*0e8cc8bdSWilliam Juul __u32 yst_rdev; /* device stuff for block and char devices (major/min) */ 329*0e8cc8bdSWilliam Juul 330*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_WINCE 331*0e8cc8bdSWilliam Juul __u32 win_ctime[2]; 332*0e8cc8bdSWilliam Juul __u32 win_atime[2]; 333*0e8cc8bdSWilliam Juul __u32 win_mtime[2]; 334*0e8cc8bdSWilliam Juul __u32 roomToGrow[4]; 335*0e8cc8bdSWilliam Juul #else 336*0e8cc8bdSWilliam Juul __u32 roomToGrow[10]; 337*0e8cc8bdSWilliam Juul #endif 338*0e8cc8bdSWilliam Juul 339*0e8cc8bdSWilliam Juul int shadowsObject; /* This object header shadows the specified object if > 0 */ 340*0e8cc8bdSWilliam Juul 341*0e8cc8bdSWilliam Juul /* isShrink applies to object headers written when we shrink the file (ie resize) */ 342*0e8cc8bdSWilliam Juul __u32 isShrink; 343*0e8cc8bdSWilliam Juul 344*0e8cc8bdSWilliam Juul } yaffs_ObjectHeader; 345*0e8cc8bdSWilliam Juul 346*0e8cc8bdSWilliam Juul /*--------------------------- Tnode -------------------------- */ 347*0e8cc8bdSWilliam Juul 348*0e8cc8bdSWilliam Juul union yaffs_Tnode_union { 349*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG 350*0e8cc8bdSWilliam Juul union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL + 1]; 351*0e8cc8bdSWilliam Juul #else 352*0e8cc8bdSWilliam Juul union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL]; 353*0e8cc8bdSWilliam Juul #endif 354*0e8cc8bdSWilliam Juul /* __u16 level0[YAFFS_NTNODES_LEVEL0]; */ 355*0e8cc8bdSWilliam Juul 356*0e8cc8bdSWilliam Juul }; 357*0e8cc8bdSWilliam Juul 358*0e8cc8bdSWilliam Juul typedef union yaffs_Tnode_union yaffs_Tnode; 359*0e8cc8bdSWilliam Juul 360*0e8cc8bdSWilliam Juul struct yaffs_TnodeList_struct { 361*0e8cc8bdSWilliam Juul struct yaffs_TnodeList_struct *next; 362*0e8cc8bdSWilliam Juul yaffs_Tnode *tnodes; 363*0e8cc8bdSWilliam Juul }; 364*0e8cc8bdSWilliam Juul 365*0e8cc8bdSWilliam Juul typedef struct yaffs_TnodeList_struct yaffs_TnodeList; 366*0e8cc8bdSWilliam Juul 367*0e8cc8bdSWilliam Juul /*------------------------ Object -----------------------------*/ 368*0e8cc8bdSWilliam Juul /* An object can be one of: 369*0e8cc8bdSWilliam Juul * - a directory (no data, has children links 370*0e8cc8bdSWilliam Juul * - a regular file (data.... not prunes :->). 371*0e8cc8bdSWilliam Juul * - a symlink [symbolic link] (the alias). 372*0e8cc8bdSWilliam Juul * - a hard link 373*0e8cc8bdSWilliam Juul */ 374*0e8cc8bdSWilliam Juul 375*0e8cc8bdSWilliam Juul typedef struct { 376*0e8cc8bdSWilliam Juul __u32 fileSize; 377*0e8cc8bdSWilliam Juul __u32 scannedFileSize; 378*0e8cc8bdSWilliam Juul __u32 shrinkSize; 379*0e8cc8bdSWilliam Juul int topLevel; 380*0e8cc8bdSWilliam Juul yaffs_Tnode *top; 381*0e8cc8bdSWilliam Juul } yaffs_FileStructure; 382*0e8cc8bdSWilliam Juul 383*0e8cc8bdSWilliam Juul typedef struct { 384*0e8cc8bdSWilliam Juul struct list_head children; /* list of child links */ 385*0e8cc8bdSWilliam Juul } yaffs_DirectoryStructure; 386*0e8cc8bdSWilliam Juul 387*0e8cc8bdSWilliam Juul typedef struct { 388*0e8cc8bdSWilliam Juul YCHAR *alias; 389*0e8cc8bdSWilliam Juul } yaffs_SymLinkStructure; 390*0e8cc8bdSWilliam Juul 391*0e8cc8bdSWilliam Juul typedef struct { 392*0e8cc8bdSWilliam Juul struct yaffs_ObjectStruct *equivalentObject; 393*0e8cc8bdSWilliam Juul __u32 equivalentObjectId; 394*0e8cc8bdSWilliam Juul } yaffs_HardLinkStructure; 395*0e8cc8bdSWilliam Juul 396*0e8cc8bdSWilliam Juul typedef union { 397*0e8cc8bdSWilliam Juul yaffs_FileStructure fileVariant; 398*0e8cc8bdSWilliam Juul yaffs_DirectoryStructure directoryVariant; 399*0e8cc8bdSWilliam Juul yaffs_SymLinkStructure symLinkVariant; 400*0e8cc8bdSWilliam Juul yaffs_HardLinkStructure hardLinkVariant; 401*0e8cc8bdSWilliam Juul } yaffs_ObjectVariant; 402*0e8cc8bdSWilliam Juul 403*0e8cc8bdSWilliam Juul struct yaffs_ObjectStruct { 404*0e8cc8bdSWilliam Juul __u8 deleted:1; /* This should only apply to unlinked files. */ 405*0e8cc8bdSWilliam Juul __u8 softDeleted:1; /* it has also been soft deleted */ 406*0e8cc8bdSWilliam Juul __u8 unlinked:1; /* An unlinked file. The file should be in the unlinked directory.*/ 407*0e8cc8bdSWilliam Juul __u8 fake:1; /* A fake object has no presence on NAND. */ 408*0e8cc8bdSWilliam Juul __u8 renameAllowed:1; /* Some objects are not allowed to be renamed. */ 409*0e8cc8bdSWilliam Juul __u8 unlinkAllowed:1; 410*0e8cc8bdSWilliam Juul __u8 dirty:1; /* the object needs to be written to flash */ 411*0e8cc8bdSWilliam Juul __u8 valid:1; /* When the file system is being loaded up, this 412*0e8cc8bdSWilliam Juul * object might be created before the data 413*0e8cc8bdSWilliam Juul * is available (ie. file data records appear before the header). 414*0e8cc8bdSWilliam Juul */ 415*0e8cc8bdSWilliam Juul __u8 lazyLoaded:1; /* This object has been lazy loaded and is missing some detail */ 416*0e8cc8bdSWilliam Juul 417*0e8cc8bdSWilliam Juul __u8 deferedFree:1; /* For Linux kernel. Object is removed from NAND, but is 418*0e8cc8bdSWilliam Juul * still in the inode cache. Free of object is defered. 419*0e8cc8bdSWilliam Juul * until the inode is released. 420*0e8cc8bdSWilliam Juul */ 421*0e8cc8bdSWilliam Juul 422*0e8cc8bdSWilliam Juul __u8 serial; /* serial number of chunk in NAND. Cached here */ 423*0e8cc8bdSWilliam Juul __u16 sum; /* sum of the name to speed searching */ 424*0e8cc8bdSWilliam Juul 425*0e8cc8bdSWilliam Juul struct yaffs_DeviceStruct *myDev; /* The device I'm on */ 426*0e8cc8bdSWilliam Juul 427*0e8cc8bdSWilliam Juul struct list_head hashLink; /* list of objects in this hash bucket */ 428*0e8cc8bdSWilliam Juul 429*0e8cc8bdSWilliam Juul struct list_head hardLinks; /* all the equivalent hard linked objects */ 430*0e8cc8bdSWilliam Juul 431*0e8cc8bdSWilliam Juul /* directory structure stuff */ 432*0e8cc8bdSWilliam Juul /* also used for linking up the free list */ 433*0e8cc8bdSWilliam Juul struct yaffs_ObjectStruct *parent; 434*0e8cc8bdSWilliam Juul struct list_head siblings; 435*0e8cc8bdSWilliam Juul 436*0e8cc8bdSWilliam Juul /* Where's my object header in NAND? */ 437*0e8cc8bdSWilliam Juul int chunkId; 438*0e8cc8bdSWilliam Juul 439*0e8cc8bdSWilliam Juul int nDataChunks; /* Number of data chunks attached to the file. */ 440*0e8cc8bdSWilliam Juul 441*0e8cc8bdSWilliam Juul __u32 objectId; /* the object id value */ 442*0e8cc8bdSWilliam Juul 443*0e8cc8bdSWilliam Juul __u32 yst_mode; 444*0e8cc8bdSWilliam Juul 445*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM 446*0e8cc8bdSWilliam Juul YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1]; 447*0e8cc8bdSWilliam Juul #endif 448*0e8cc8bdSWilliam Juul 449*0e8cc8bdSWilliam Juul #ifndef __KERNEL__ 450*0e8cc8bdSWilliam Juul __u32 inUse; 451*0e8cc8bdSWilliam Juul #endif 452*0e8cc8bdSWilliam Juul 453*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_WINCE 454*0e8cc8bdSWilliam Juul __u32 win_ctime[2]; 455*0e8cc8bdSWilliam Juul __u32 win_mtime[2]; 456*0e8cc8bdSWilliam Juul __u32 win_atime[2]; 457*0e8cc8bdSWilliam Juul #else 458*0e8cc8bdSWilliam Juul __u32 yst_uid; 459*0e8cc8bdSWilliam Juul __u32 yst_gid; 460*0e8cc8bdSWilliam Juul __u32 yst_atime; 461*0e8cc8bdSWilliam Juul __u32 yst_mtime; 462*0e8cc8bdSWilliam Juul __u32 yst_ctime; 463*0e8cc8bdSWilliam Juul #endif 464*0e8cc8bdSWilliam Juul 465*0e8cc8bdSWilliam Juul __u32 yst_rdev; 466*0e8cc8bdSWilliam Juul 467*0e8cc8bdSWilliam Juul #ifdef __KERNEL__ 468*0e8cc8bdSWilliam Juul struct inode *myInode; 469*0e8cc8bdSWilliam Juul 470*0e8cc8bdSWilliam Juul #endif 471*0e8cc8bdSWilliam Juul 472*0e8cc8bdSWilliam Juul yaffs_ObjectType variantType; 473*0e8cc8bdSWilliam Juul 474*0e8cc8bdSWilliam Juul yaffs_ObjectVariant variant; 475*0e8cc8bdSWilliam Juul 476*0e8cc8bdSWilliam Juul }; 477*0e8cc8bdSWilliam Juul 478*0e8cc8bdSWilliam Juul typedef struct yaffs_ObjectStruct yaffs_Object; 479*0e8cc8bdSWilliam Juul 480*0e8cc8bdSWilliam Juul struct yaffs_ObjectList_struct { 481*0e8cc8bdSWilliam Juul yaffs_Object *objects; 482*0e8cc8bdSWilliam Juul struct yaffs_ObjectList_struct *next; 483*0e8cc8bdSWilliam Juul }; 484*0e8cc8bdSWilliam Juul 485*0e8cc8bdSWilliam Juul typedef struct yaffs_ObjectList_struct yaffs_ObjectList; 486*0e8cc8bdSWilliam Juul 487*0e8cc8bdSWilliam Juul typedef struct { 488*0e8cc8bdSWilliam Juul struct list_head list; 489*0e8cc8bdSWilliam Juul int count; 490*0e8cc8bdSWilliam Juul } yaffs_ObjectBucket; 491*0e8cc8bdSWilliam Juul 492*0e8cc8bdSWilliam Juul 493*0e8cc8bdSWilliam Juul /* yaffs_CheckpointObject holds the definition of an object as dumped 494*0e8cc8bdSWilliam Juul * by checkpointing. 495*0e8cc8bdSWilliam Juul */ 496*0e8cc8bdSWilliam Juul 497*0e8cc8bdSWilliam Juul typedef struct { 498*0e8cc8bdSWilliam Juul int structType; 499*0e8cc8bdSWilliam Juul __u32 objectId; 500*0e8cc8bdSWilliam Juul __u32 parentId; 501*0e8cc8bdSWilliam Juul int chunkId; 502*0e8cc8bdSWilliam Juul 503*0e8cc8bdSWilliam Juul yaffs_ObjectType variantType:3; 504*0e8cc8bdSWilliam Juul __u8 deleted:1; 505*0e8cc8bdSWilliam Juul __u8 softDeleted:1; 506*0e8cc8bdSWilliam Juul __u8 unlinked:1; 507*0e8cc8bdSWilliam Juul __u8 fake:1; 508*0e8cc8bdSWilliam Juul __u8 renameAllowed:1; 509*0e8cc8bdSWilliam Juul __u8 unlinkAllowed:1; 510*0e8cc8bdSWilliam Juul __u8 serial; 511*0e8cc8bdSWilliam Juul 512*0e8cc8bdSWilliam Juul int nDataChunks; 513*0e8cc8bdSWilliam Juul __u32 fileSizeOrEquivalentObjectId; 514*0e8cc8bdSWilliam Juul 515*0e8cc8bdSWilliam Juul }yaffs_CheckpointObject; 516*0e8cc8bdSWilliam Juul 517*0e8cc8bdSWilliam Juul /*--------------------- Temporary buffers ---------------- 518*0e8cc8bdSWilliam Juul * 519*0e8cc8bdSWilliam Juul * These are chunk-sized working buffers. Each device has a few 520*0e8cc8bdSWilliam Juul */ 521*0e8cc8bdSWilliam Juul 522*0e8cc8bdSWilliam Juul typedef struct { 523*0e8cc8bdSWilliam Juul __u8 *buffer; 524*0e8cc8bdSWilliam Juul int line; /* track from whence this buffer was allocated */ 525*0e8cc8bdSWilliam Juul int maxLine; 526*0e8cc8bdSWilliam Juul } yaffs_TempBuffer; 527*0e8cc8bdSWilliam Juul 528*0e8cc8bdSWilliam Juul /*----------------- Device ---------------------------------*/ 529*0e8cc8bdSWilliam Juul 530*0e8cc8bdSWilliam Juul struct yaffs_DeviceStruct { 531*0e8cc8bdSWilliam Juul struct list_head devList; 532*0e8cc8bdSWilliam Juul const char *name; 533*0e8cc8bdSWilliam Juul 534*0e8cc8bdSWilliam Juul /* Entry parameters set up way early. Yaffs sets up the rest.*/ 535*0e8cc8bdSWilliam Juul int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */ 536*0e8cc8bdSWilliam Juul int nChunksPerBlock; /* does not need to be a power of 2 */ 537*0e8cc8bdSWilliam Juul int nBytesPerSpare; /* spare area size */ 538*0e8cc8bdSWilliam Juul int startBlock; /* Start block we're allowed to use */ 539*0e8cc8bdSWilliam Juul int endBlock; /* End block we're allowed to use */ 540*0e8cc8bdSWilliam Juul int nReservedBlocks; /* We want this tuneable so that we can reduce */ 541*0e8cc8bdSWilliam Juul /* reserved blocks on NOR and RAM. */ 542*0e8cc8bdSWilliam Juul 543*0e8cc8bdSWilliam Juul 544*0e8cc8bdSWilliam Juul /* Stuff used by the shared space checkpointing mechanism */ 545*0e8cc8bdSWilliam Juul /* If this value is zero, then this mechanism is disabled */ 546*0e8cc8bdSWilliam Juul 547*0e8cc8bdSWilliam Juul int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ 548*0e8cc8bdSWilliam Juul 549*0e8cc8bdSWilliam Juul 550*0e8cc8bdSWilliam Juul 551*0e8cc8bdSWilliam Juul 552*0e8cc8bdSWilliam Juul int nShortOpCaches; /* If <= 0, then short op caching is disabled, else 553*0e8cc8bdSWilliam Juul * the number of short op caches (don't use too many) 554*0e8cc8bdSWilliam Juul */ 555*0e8cc8bdSWilliam Juul 556*0e8cc8bdSWilliam Juul int useHeaderFileSize; /* Flag to determine if we should use file sizes from the header */ 557*0e8cc8bdSWilliam Juul 558*0e8cc8bdSWilliam Juul int useNANDECC; /* Flag to decide whether or not to use NANDECC */ 559*0e8cc8bdSWilliam Juul 560*0e8cc8bdSWilliam Juul void *genericDevice; /* Pointer to device context 561*0e8cc8bdSWilliam Juul * On an mtd this holds the mtd pointer. 562*0e8cc8bdSWilliam Juul */ 563*0e8cc8bdSWilliam Juul void *superBlock; 564*0e8cc8bdSWilliam Juul 565*0e8cc8bdSWilliam Juul /* NAND access functions (Must be set before calling YAFFS)*/ 566*0e8cc8bdSWilliam Juul 567*0e8cc8bdSWilliam Juul int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev, 568*0e8cc8bdSWilliam Juul int chunkInNAND, const __u8 * data, 569*0e8cc8bdSWilliam Juul const yaffs_Spare * spare); 570*0e8cc8bdSWilliam Juul int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev, 571*0e8cc8bdSWilliam Juul int chunkInNAND, __u8 * data, 572*0e8cc8bdSWilliam Juul yaffs_Spare * spare); 573*0e8cc8bdSWilliam Juul int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, 574*0e8cc8bdSWilliam Juul int blockInNAND); 575*0e8cc8bdSWilliam Juul int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); 576*0e8cc8bdSWilliam Juul 577*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_YAFFS2 578*0e8cc8bdSWilliam Juul int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, 579*0e8cc8bdSWilliam Juul int chunkInNAND, const __u8 * data, 580*0e8cc8bdSWilliam Juul const yaffs_ExtendedTags * tags); 581*0e8cc8bdSWilliam Juul int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev, 582*0e8cc8bdSWilliam Juul int chunkInNAND, __u8 * data, 583*0e8cc8bdSWilliam Juul yaffs_ExtendedTags * tags); 584*0e8cc8bdSWilliam Juul int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo); 585*0e8cc8bdSWilliam Juul int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo, 586*0e8cc8bdSWilliam Juul yaffs_BlockState * state, int *sequenceNumber); 587*0e8cc8bdSWilliam Juul #endif 588*0e8cc8bdSWilliam Juul 589*0e8cc8bdSWilliam Juul int isYaffs2; 590*0e8cc8bdSWilliam Juul 591*0e8cc8bdSWilliam Juul /* The removeObjectCallback function must be supplied by OS flavours that 592*0e8cc8bdSWilliam Juul * need it. The Linux kernel does not use this, but yaffs direct does use 593*0e8cc8bdSWilliam Juul * it to implement the faster readdir 594*0e8cc8bdSWilliam Juul */ 595*0e8cc8bdSWilliam Juul void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj); 596*0e8cc8bdSWilliam Juul 597*0e8cc8bdSWilliam Juul /* Callback to mark the superblock dirsty */ 598*0e8cc8bdSWilliam Juul void (*markSuperBlockDirty)(void * superblock); 599*0e8cc8bdSWilliam Juul 600*0e8cc8bdSWilliam Juul int wideTnodesDisabled; /* Set to disable wide tnodes */ 601*0e8cc8bdSWilliam Juul 602*0e8cc8bdSWilliam Juul 603*0e8cc8bdSWilliam Juul /* End of stuff that must be set before initialisation. */ 604*0e8cc8bdSWilliam Juul 605*0e8cc8bdSWilliam Juul /* Checkpoint control. Can be set before or after initialisation */ 606*0e8cc8bdSWilliam Juul __u8 skipCheckpointRead; 607*0e8cc8bdSWilliam Juul __u8 skipCheckpointWrite; 608*0e8cc8bdSWilliam Juul 609*0e8cc8bdSWilliam Juul /* Runtime parameters. Set up by YAFFS. */ 610*0e8cc8bdSWilliam Juul 611*0e8cc8bdSWilliam Juul __u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */ 612*0e8cc8bdSWilliam Juul __u16 chunkGroupSize; /* == 2^^chunkGroupBits */ 613*0e8cc8bdSWilliam Juul 614*0e8cc8bdSWilliam Juul /* Stuff to support wide tnodes */ 615*0e8cc8bdSWilliam Juul __u32 tnodeWidth; 616*0e8cc8bdSWilliam Juul __u32 tnodeMask; 617*0e8cc8bdSWilliam Juul 618*0e8cc8bdSWilliam Juul /* Stuff to support various file offses to chunk/offset translations */ 619*0e8cc8bdSWilliam Juul /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */ 620*0e8cc8bdSWilliam Juul __u32 crumbMask; 621*0e8cc8bdSWilliam Juul __u32 crumbShift; 622*0e8cc8bdSWilliam Juul __u32 crumbsPerChunk; 623*0e8cc8bdSWilliam Juul 624*0e8cc8bdSWilliam Juul /* Straight shifting for nDataBytesPerChunk being a power of 2 */ 625*0e8cc8bdSWilliam Juul __u32 chunkShift; 626*0e8cc8bdSWilliam Juul __u32 chunkMask; 627*0e8cc8bdSWilliam Juul 628*0e8cc8bdSWilliam Juul 629*0e8cc8bdSWilliam Juul #ifdef __KERNEL__ 630*0e8cc8bdSWilliam Juul 631*0e8cc8bdSWilliam Juul struct semaphore sem; /* Semaphore for waiting on erasure.*/ 632*0e8cc8bdSWilliam Juul struct semaphore grossLock; /* Gross locking semaphore */ 633*0e8cc8bdSWilliam Juul __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer 634*0e8cc8bdSWilliam Juul * at compile time so we have to allocate it. 635*0e8cc8bdSWilliam Juul */ 636*0e8cc8bdSWilliam Juul void (*putSuperFunc) (struct super_block * sb); 637*0e8cc8bdSWilliam Juul #endif 638*0e8cc8bdSWilliam Juul 639*0e8cc8bdSWilliam Juul int isMounted; 640*0e8cc8bdSWilliam Juul 641*0e8cc8bdSWilliam Juul int isCheckpointed; 642*0e8cc8bdSWilliam Juul 643*0e8cc8bdSWilliam Juul 644*0e8cc8bdSWilliam Juul /* Stuff to support block offsetting to support start block zero */ 645*0e8cc8bdSWilliam Juul int internalStartBlock; 646*0e8cc8bdSWilliam Juul int internalEndBlock; 647*0e8cc8bdSWilliam Juul int blockOffset; 648*0e8cc8bdSWilliam Juul int chunkOffset; 649*0e8cc8bdSWilliam Juul 650*0e8cc8bdSWilliam Juul 651*0e8cc8bdSWilliam Juul /* Runtime checkpointing stuff */ 652*0e8cc8bdSWilliam Juul int checkpointPageSequence; /* running sequence number of checkpoint pages */ 653*0e8cc8bdSWilliam Juul int checkpointByteCount; 654*0e8cc8bdSWilliam Juul int checkpointByteOffset; 655*0e8cc8bdSWilliam Juul __u8 *checkpointBuffer; 656*0e8cc8bdSWilliam Juul int checkpointOpenForWrite; 657*0e8cc8bdSWilliam Juul int blocksInCheckpoint; 658*0e8cc8bdSWilliam Juul int checkpointCurrentChunk; 659*0e8cc8bdSWilliam Juul int checkpointCurrentBlock; 660*0e8cc8bdSWilliam Juul int checkpointNextBlock; 661*0e8cc8bdSWilliam Juul int *checkpointBlockList; 662*0e8cc8bdSWilliam Juul int checkpointMaxBlocks; 663*0e8cc8bdSWilliam Juul __u32 checkpointSum; 664*0e8cc8bdSWilliam Juul __u32 checkpointXor; 665*0e8cc8bdSWilliam Juul 666*0e8cc8bdSWilliam Juul /* Block Info */ 667*0e8cc8bdSWilliam Juul yaffs_BlockInfo *blockInfo; 668*0e8cc8bdSWilliam Juul __u8 *chunkBits; /* bitmap of chunks in use */ 669*0e8cc8bdSWilliam Juul unsigned blockInfoAlt:1; /* was allocated using alternative strategy */ 670*0e8cc8bdSWilliam Juul unsigned chunkBitsAlt:1; /* was allocated using alternative strategy */ 671*0e8cc8bdSWilliam Juul int chunkBitmapStride; /* Number of bytes of chunkBits per block. 672*0e8cc8bdSWilliam Juul * Must be consistent with nChunksPerBlock. 673*0e8cc8bdSWilliam Juul */ 674*0e8cc8bdSWilliam Juul 675*0e8cc8bdSWilliam Juul int nErasedBlocks; 676*0e8cc8bdSWilliam Juul int allocationBlock; /* Current block being allocated off */ 677*0e8cc8bdSWilliam Juul __u32 allocationPage; 678*0e8cc8bdSWilliam Juul int allocationBlockFinder; /* Used to search for next allocation block */ 679*0e8cc8bdSWilliam Juul 680*0e8cc8bdSWilliam Juul /* Runtime state */ 681*0e8cc8bdSWilliam Juul int nTnodesCreated; 682*0e8cc8bdSWilliam Juul yaffs_Tnode *freeTnodes; 683*0e8cc8bdSWilliam Juul int nFreeTnodes; 684*0e8cc8bdSWilliam Juul yaffs_TnodeList *allocatedTnodeList; 685*0e8cc8bdSWilliam Juul 686*0e8cc8bdSWilliam Juul int isDoingGC; 687*0e8cc8bdSWilliam Juul 688*0e8cc8bdSWilliam Juul int nObjectsCreated; 689*0e8cc8bdSWilliam Juul yaffs_Object *freeObjects; 690*0e8cc8bdSWilliam Juul int nFreeObjects; 691*0e8cc8bdSWilliam Juul 692*0e8cc8bdSWilliam Juul yaffs_ObjectList *allocatedObjectList; 693*0e8cc8bdSWilliam Juul 694*0e8cc8bdSWilliam Juul yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS]; 695*0e8cc8bdSWilliam Juul 696*0e8cc8bdSWilliam Juul int nFreeChunks; 697*0e8cc8bdSWilliam Juul 698*0e8cc8bdSWilliam Juul int currentDirtyChecker; /* Used to find current dirtiest block */ 699*0e8cc8bdSWilliam Juul 700*0e8cc8bdSWilliam Juul __u32 *gcCleanupList; /* objects to delete at the end of a GC. */ 701*0e8cc8bdSWilliam Juul int nonAggressiveSkip; /* GC state/mode */ 702*0e8cc8bdSWilliam Juul 703*0e8cc8bdSWilliam Juul /* Statistcs */ 704*0e8cc8bdSWilliam Juul int nPageWrites; 705*0e8cc8bdSWilliam Juul int nPageReads; 706*0e8cc8bdSWilliam Juul int nBlockErasures; 707*0e8cc8bdSWilliam Juul int nErasureFailures; 708*0e8cc8bdSWilliam Juul int nGCCopies; 709*0e8cc8bdSWilliam Juul int garbageCollections; 710*0e8cc8bdSWilliam Juul int passiveGarbageCollections; 711*0e8cc8bdSWilliam Juul int nRetriedWrites; 712*0e8cc8bdSWilliam Juul int nRetiredBlocks; 713*0e8cc8bdSWilliam Juul int eccFixed; 714*0e8cc8bdSWilliam Juul int eccUnfixed; 715*0e8cc8bdSWilliam Juul int tagsEccFixed; 716*0e8cc8bdSWilliam Juul int tagsEccUnfixed; 717*0e8cc8bdSWilliam Juul int nDeletions; 718*0e8cc8bdSWilliam Juul int nUnmarkedDeletions; 719*0e8cc8bdSWilliam Juul 720*0e8cc8bdSWilliam Juul int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */ 721*0e8cc8bdSWilliam Juul 722*0e8cc8bdSWilliam Juul /* Special directories */ 723*0e8cc8bdSWilliam Juul yaffs_Object *rootDir; 724*0e8cc8bdSWilliam Juul yaffs_Object *lostNFoundDir; 725*0e8cc8bdSWilliam Juul 726*0e8cc8bdSWilliam Juul /* Buffer areas for storing data to recover from write failures TODO 727*0e8cc8bdSWilliam Juul * __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; 728*0e8cc8bdSWilliam Juul * yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK]; 729*0e8cc8bdSWilliam Juul */ 730*0e8cc8bdSWilliam Juul 731*0e8cc8bdSWilliam Juul int bufferedBlock; /* Which block is buffered here? */ 732*0e8cc8bdSWilliam Juul int doingBufferedBlockRewrite; 733*0e8cc8bdSWilliam Juul 734*0e8cc8bdSWilliam Juul yaffs_ChunkCache *srCache; 735*0e8cc8bdSWilliam Juul int srLastUse; 736*0e8cc8bdSWilliam Juul 737*0e8cc8bdSWilliam Juul int cacheHits; 738*0e8cc8bdSWilliam Juul 739*0e8cc8bdSWilliam Juul /* Stuff for background deletion and unlinked files.*/ 740*0e8cc8bdSWilliam Juul yaffs_Object *unlinkedDir; /* Directory where unlinked and deleted files live. */ 741*0e8cc8bdSWilliam Juul yaffs_Object *deletedDir; /* Directory where deleted objects are sent to disappear. */ 742*0e8cc8bdSWilliam Juul yaffs_Object *unlinkedDeletion; /* Current file being background deleted.*/ 743*0e8cc8bdSWilliam Juul int nDeletedFiles; /* Count of files awaiting deletion;*/ 744*0e8cc8bdSWilliam Juul int nUnlinkedFiles; /* Count of unlinked files. */ 745*0e8cc8bdSWilliam Juul int nBackgroundDeletions; /* Count of background deletions. */ 746*0e8cc8bdSWilliam Juul 747*0e8cc8bdSWilliam Juul 748*0e8cc8bdSWilliam Juul yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS]; 749*0e8cc8bdSWilliam Juul int maxTemp; 750*0e8cc8bdSWilliam Juul int unmanagedTempAllocations; 751*0e8cc8bdSWilliam Juul int unmanagedTempDeallocations; 752*0e8cc8bdSWilliam Juul 753*0e8cc8bdSWilliam Juul /* yaffs2 runtime stuff */ 754*0e8cc8bdSWilliam Juul unsigned sequenceNumber; /* Sequence number of currently allocating block */ 755*0e8cc8bdSWilliam Juul unsigned oldestDirtySequence; 756*0e8cc8bdSWilliam Juul 757*0e8cc8bdSWilliam Juul }; 758*0e8cc8bdSWilliam Juul 759*0e8cc8bdSWilliam Juul typedef struct yaffs_DeviceStruct yaffs_Device; 760*0e8cc8bdSWilliam Juul 761*0e8cc8bdSWilliam Juul /* The static layout of bllock usage etc is stored in the super block header */ 762*0e8cc8bdSWilliam Juul typedef struct { 763*0e8cc8bdSWilliam Juul int StructType; 764*0e8cc8bdSWilliam Juul int version; 765*0e8cc8bdSWilliam Juul int checkpointStartBlock; 766*0e8cc8bdSWilliam Juul int checkpointEndBlock; 767*0e8cc8bdSWilliam Juul int startBlock; 768*0e8cc8bdSWilliam Juul int endBlock; 769*0e8cc8bdSWilliam Juul int rfu[100]; 770*0e8cc8bdSWilliam Juul } yaffs_SuperBlockHeader; 771*0e8cc8bdSWilliam Juul 772*0e8cc8bdSWilliam Juul /* The CheckpointDevice structure holds the device information that changes at runtime and 773*0e8cc8bdSWilliam Juul * must be preserved over unmount/mount cycles. 774*0e8cc8bdSWilliam Juul */ 775*0e8cc8bdSWilliam Juul typedef struct { 776*0e8cc8bdSWilliam Juul int structType; 777*0e8cc8bdSWilliam Juul int nErasedBlocks; 778*0e8cc8bdSWilliam Juul int allocationBlock; /* Current block being allocated off */ 779*0e8cc8bdSWilliam Juul __u32 allocationPage; 780*0e8cc8bdSWilliam Juul int nFreeChunks; 781*0e8cc8bdSWilliam Juul 782*0e8cc8bdSWilliam Juul int nDeletedFiles; /* Count of files awaiting deletion;*/ 783*0e8cc8bdSWilliam Juul int nUnlinkedFiles; /* Count of unlinked files. */ 784*0e8cc8bdSWilliam Juul int nBackgroundDeletions; /* Count of background deletions. */ 785*0e8cc8bdSWilliam Juul 786*0e8cc8bdSWilliam Juul /* yaffs2 runtime stuff */ 787*0e8cc8bdSWilliam Juul unsigned sequenceNumber; /* Sequence number of currently allocating block */ 788*0e8cc8bdSWilliam Juul unsigned oldestDirtySequence; 789*0e8cc8bdSWilliam Juul 790*0e8cc8bdSWilliam Juul } yaffs_CheckpointDevice; 791*0e8cc8bdSWilliam Juul 792*0e8cc8bdSWilliam Juul 793*0e8cc8bdSWilliam Juul typedef struct { 794*0e8cc8bdSWilliam Juul int structType; 795*0e8cc8bdSWilliam Juul __u32 magic; 796*0e8cc8bdSWilliam Juul __u32 version; 797*0e8cc8bdSWilliam Juul __u32 head; 798*0e8cc8bdSWilliam Juul } yaffs_CheckpointValidity; 799*0e8cc8bdSWilliam Juul 800*0e8cc8bdSWilliam Juul /* Function to manipulate block info */ 801*0e8cc8bdSWilliam Juul static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) 802*0e8cc8bdSWilliam Juul { 803*0e8cc8bdSWilliam Juul if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { 804*0e8cc8bdSWilliam Juul T(YAFFS_TRACE_ERROR, 805*0e8cc8bdSWilliam Juul (TSTR 806*0e8cc8bdSWilliam Juul ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), 807*0e8cc8bdSWilliam Juul blk)); 808*0e8cc8bdSWilliam Juul YBUG(); 809*0e8cc8bdSWilliam Juul } 810*0e8cc8bdSWilliam Juul return &dev->blockInfo[blk - dev->internalStartBlock]; 811*0e8cc8bdSWilliam Juul } 812*0e8cc8bdSWilliam Juul 813*0e8cc8bdSWilliam Juul /*----------------------- YAFFS Functions -----------------------*/ 814*0e8cc8bdSWilliam Juul 815*0e8cc8bdSWilliam Juul int yaffs_GutsInitialise(yaffs_Device * dev); 816*0e8cc8bdSWilliam Juul void yaffs_Deinitialise(yaffs_Device * dev); 817*0e8cc8bdSWilliam Juul 818*0e8cc8bdSWilliam Juul int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev); 819*0e8cc8bdSWilliam Juul 820*0e8cc8bdSWilliam Juul int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, 821*0e8cc8bdSWilliam Juul yaffs_Object * newDir, const YCHAR * newName); 822*0e8cc8bdSWilliam Juul 823*0e8cc8bdSWilliam Juul int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name); 824*0e8cc8bdSWilliam Juul int yaffs_DeleteFile(yaffs_Object * obj); 825*0e8cc8bdSWilliam Juul 826*0e8cc8bdSWilliam Juul int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize); 827*0e8cc8bdSWilliam Juul int yaffs_GetObjectFileLength(yaffs_Object * obj); 828*0e8cc8bdSWilliam Juul int yaffs_GetObjectInode(yaffs_Object * obj); 829*0e8cc8bdSWilliam Juul unsigned yaffs_GetObjectType(yaffs_Object * obj); 830*0e8cc8bdSWilliam Juul int yaffs_GetObjectLinkCount(yaffs_Object * obj); 831*0e8cc8bdSWilliam Juul 832*0e8cc8bdSWilliam Juul int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr); 833*0e8cc8bdSWilliam Juul int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr); 834*0e8cc8bdSWilliam Juul 835*0e8cc8bdSWilliam Juul /* File operations */ 836*0e8cc8bdSWilliam Juul int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset, 837*0e8cc8bdSWilliam Juul int nBytes); 838*0e8cc8bdSWilliam Juul int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset, 839*0e8cc8bdSWilliam Juul int nBytes, int writeThrough); 840*0e8cc8bdSWilliam Juul int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize); 841*0e8cc8bdSWilliam Juul 842*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, 843*0e8cc8bdSWilliam Juul __u32 mode, __u32 uid, __u32 gid); 844*0e8cc8bdSWilliam Juul int yaffs_FlushFile(yaffs_Object * obj, int updateTime); 845*0e8cc8bdSWilliam Juul 846*0e8cc8bdSWilliam Juul /* Flushing and checkpointing */ 847*0e8cc8bdSWilliam Juul void yaffs_FlushEntireDeviceCache(yaffs_Device *dev); 848*0e8cc8bdSWilliam Juul 849*0e8cc8bdSWilliam Juul int yaffs_CheckpointSave(yaffs_Device *dev); 850*0e8cc8bdSWilliam Juul int yaffs_CheckpointRestore(yaffs_Device *dev); 851*0e8cc8bdSWilliam Juul 852*0e8cc8bdSWilliam Juul /* Directory operations */ 853*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, 854*0e8cc8bdSWilliam Juul __u32 mode, __u32 uid, __u32 gid); 855*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name); 856*0e8cc8bdSWilliam Juul int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, 857*0e8cc8bdSWilliam Juul int (*fn) (yaffs_Object *)); 858*0e8cc8bdSWilliam Juul 859*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number); 860*0e8cc8bdSWilliam Juul 861*0e8cc8bdSWilliam Juul /* Link operations */ 862*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, 863*0e8cc8bdSWilliam Juul yaffs_Object * equivalentObject); 864*0e8cc8bdSWilliam Juul 865*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj); 866*0e8cc8bdSWilliam Juul 867*0e8cc8bdSWilliam Juul /* Symlink operations */ 868*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, 869*0e8cc8bdSWilliam Juul __u32 mode, __u32 uid, __u32 gid, 870*0e8cc8bdSWilliam Juul const YCHAR * alias); 871*0e8cc8bdSWilliam Juul YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj); 872*0e8cc8bdSWilliam Juul 873*0e8cc8bdSWilliam Juul /* Special inodes (fifos, sockets and devices) */ 874*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, 875*0e8cc8bdSWilliam Juul __u32 mode, __u32 uid, __u32 gid, __u32 rdev); 876*0e8cc8bdSWilliam Juul 877*0e8cc8bdSWilliam Juul /* Special directories */ 878*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_Root(yaffs_Device * dev); 879*0e8cc8bdSWilliam Juul yaffs_Object *yaffs_LostNFound(yaffs_Device * dev); 880*0e8cc8bdSWilliam Juul 881*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_WINCE 882*0e8cc8bdSWilliam Juul /* CONFIG_YAFFS_WINCE special stuff */ 883*0e8cc8bdSWilliam Juul void yfsd_WinFileTimeNow(__u32 target[2]); 884*0e8cc8bdSWilliam Juul #endif 885*0e8cc8bdSWilliam Juul 886*0e8cc8bdSWilliam Juul #ifdef __KERNEL__ 887*0e8cc8bdSWilliam Juul 888*0e8cc8bdSWilliam Juul void yaffs_HandleDeferedFree(yaffs_Object * obj); 889*0e8cc8bdSWilliam Juul #endif 890*0e8cc8bdSWilliam Juul 891*0e8cc8bdSWilliam Juul /* Debug dump */ 892*0e8cc8bdSWilliam Juul int yaffs_DumpObject(yaffs_Object * obj); 893*0e8cc8bdSWilliam Juul 894*0e8cc8bdSWilliam Juul void yaffs_GutsTest(yaffs_Device * dev); 895*0e8cc8bdSWilliam Juul 896*0e8cc8bdSWilliam Juul /* A few useful functions */ 897*0e8cc8bdSWilliam Juul void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); 898*0e8cc8bdSWilliam Juul void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn); 899*0e8cc8bdSWilliam Juul int yaffs_CheckFF(__u8 * buffer, int nBytes); 900*0e8cc8bdSWilliam Juul void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi); 901*0e8cc8bdSWilliam Juul 902*0e8cc8bdSWilliam Juul #endif 903