10e8cc8bdSWilliam Juul /* 20e8cc8bdSWilliam Juul * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 30e8cc8bdSWilliam Juul * 4*753ac610SCharles Manning * Copyright (C) 2002-2011 Aleph One Ltd. 50e8cc8bdSWilliam Juul * for Toby Churchill Ltd and Brightstar Engineering 60e8cc8bdSWilliam Juul * 70e8cc8bdSWilliam Juul * Created by Charles Manning <charles@aleph1.co.uk> 80e8cc8bdSWilliam Juul * 90e8cc8bdSWilliam Juul * This program is free software; you can redistribute it and/or modify 100e8cc8bdSWilliam Juul * it under the terms of the GNU Lesser General Public License version 2.1 as 110e8cc8bdSWilliam Juul * published by the Free Software Foundation. 120e8cc8bdSWilliam Juul * 130e8cc8bdSWilliam Juul * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. 140e8cc8bdSWilliam Juul */ 150e8cc8bdSWilliam Juul 160e8cc8bdSWilliam Juul #ifndef __YAFFS_GUTS_H__ 170e8cc8bdSWilliam Juul #define __YAFFS_GUTS_H__ 180e8cc8bdSWilliam Juul 190e8cc8bdSWilliam Juul #include "yportenv.h" 200e8cc8bdSWilliam Juul 210e8cc8bdSWilliam Juul #define YAFFS_OK 1 220e8cc8bdSWilliam Juul #define YAFFS_FAIL 0 230e8cc8bdSWilliam Juul 240e8cc8bdSWilliam Juul /* Give us a Y=0x59, 250e8cc8bdSWilliam Juul * Give us an A=0x41, 26*753ac610SCharles Manning * Give us an FF=0xff 270e8cc8bdSWilliam Juul * Give us an S=0x53 280e8cc8bdSWilliam Juul * And what have we got... 290e8cc8bdSWilliam Juul */ 30*753ac610SCharles Manning #define YAFFS_MAGIC 0x5941ff53 310e8cc8bdSWilliam Juul 32*753ac610SCharles Manning /* 33*753ac610SCharles Manning * Tnodes form a tree with the tnodes in "levels" 34*753ac610SCharles Manning * Levels greater than 0 hold 8 slots which point to other tnodes. 35*753ac610SCharles Manning * Those at level 0 hold 16 slots which point to chunks in NAND. 36*753ac610SCharles Manning * 37*753ac610SCharles Manning * A maximum level of 8 thust supports files of size up to: 38*753ac610SCharles Manning * 39*753ac610SCharles Manning * 2^(3*MAX_LEVEL+4) 40*753ac610SCharles Manning * 41*753ac610SCharles Manning * Thus a max level of 8 supports files with up to 2^^28 chunks which gives 42*753ac610SCharles Manning * a maximum file size of arounf 51Gbytees with 2k chunks. 43*753ac610SCharles Manning */ 440e8cc8bdSWilliam Juul #define YAFFS_NTNODES_LEVEL0 16 450e8cc8bdSWilliam Juul #define YAFFS_TNODES_LEVEL0_BITS 4 460e8cc8bdSWilliam Juul #define YAFFS_TNODES_LEVEL0_MASK 0xf 470e8cc8bdSWilliam Juul 480e8cc8bdSWilliam Juul #define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2) 490e8cc8bdSWilliam Juul #define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1) 500e8cc8bdSWilliam Juul #define YAFFS_TNODES_INTERNAL_MASK 0x7 51*753ac610SCharles Manning #define YAFFS_TNODES_MAX_LEVEL 8 52*753ac610SCharles Manning #define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \ 53*753ac610SCharles Manning YAFFS_TNODES_INTERNAL_BITS * \ 54*753ac610SCharles Manning YAFFS_TNODES_MAX_LEVEL) 55*753ac610SCharles Manning #define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1) 560e8cc8bdSWilliam Juul 57*753ac610SCharles Manning /* Constants for YAFFS1 mode */ 580e8cc8bdSWilliam Juul #define YAFFS_BYTES_PER_SPARE 16 590e8cc8bdSWilliam Juul #define YAFFS_BYTES_PER_CHUNK 512 600e8cc8bdSWilliam Juul #define YAFFS_CHUNK_SIZE_SHIFT 9 610e8cc8bdSWilliam Juul #define YAFFS_CHUNKS_PER_BLOCK 32 620e8cc8bdSWilliam Juul #define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) 630e8cc8bdSWilliam Juul 640e8cc8bdSWilliam Juul #define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024 650e8cc8bdSWilliam Juul #define YAFFS_MIN_YAFFS2_SPARE_SIZE 32 660e8cc8bdSWilliam Juul 670e8cc8bdSWilliam Juul 680e8cc8bdSWilliam Juul 690e8cc8bdSWilliam Juul #define YAFFS_ALLOCATION_NOBJECTS 100 700e8cc8bdSWilliam Juul #define YAFFS_ALLOCATION_NTNODES 100 710e8cc8bdSWilliam Juul #define YAFFS_ALLOCATION_NLINKS 100 720e8cc8bdSWilliam Juul 730e8cc8bdSWilliam Juul #define YAFFS_NOBJECT_BUCKETS 256 740e8cc8bdSWilliam Juul 750e8cc8bdSWilliam Juul #define YAFFS_OBJECT_SPACE 0x40000 76*753ac610SCharles Manning #define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1) 770e8cc8bdSWilliam Juul 78*753ac610SCharles Manning /* Binary data version stamps */ 79*753ac610SCharles Manning #define YAFFS_SUMMARY_VERSION 1 80*753ac610SCharles Manning #define YAFFS_CHECKPOINT_VERSION 6 810e8cc8bdSWilliam Juul 820e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_UNICODE 830e8cc8bdSWilliam Juul #define YAFFS_MAX_NAME_LENGTH 127 840e8cc8bdSWilliam Juul #define YAFFS_MAX_ALIAS_LENGTH 79 850e8cc8bdSWilliam Juul #else 860e8cc8bdSWilliam Juul #define YAFFS_MAX_NAME_LENGTH 255 870e8cc8bdSWilliam Juul #define YAFFS_MAX_ALIAS_LENGTH 159 880e8cc8bdSWilliam Juul #endif 890e8cc8bdSWilliam Juul 900e8cc8bdSWilliam Juul #define YAFFS_SHORT_NAME_LENGTH 15 910e8cc8bdSWilliam Juul 920e8cc8bdSWilliam Juul /* Some special object ids for pseudo objects */ 930e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_ROOT 1 940e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_LOSTNFOUND 2 950e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_UNLINKED 3 960e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_DELETED 4 970e8cc8bdSWilliam Juul 98*753ac610SCharles Manning /* Fake object Id for summary data */ 99*753ac610SCharles Manning #define YAFFS_OBJECTID_SUMMARY 0x10 100*753ac610SCharles Manning 101*753ac610SCharles Manning /* Pseudo object ids for checkpointing */ 1020e8cc8bdSWilliam Juul #define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20 1030e8cc8bdSWilliam Juul #define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21 1040e8cc8bdSWilliam Juul 1050e8cc8bdSWilliam Juul #define YAFFS_MAX_SHORT_OP_CACHES 20 1060e8cc8bdSWilliam Juul 107*753ac610SCharles Manning #define YAFFS_N_TEMP_BUFFERS 6 1080e8cc8bdSWilliam Juul 1090e8cc8bdSWilliam Juul /* We limit the number attempts at sucessfully saving a chunk of data. 1100e8cc8bdSWilliam Juul * Small-page devices have 32 pages per block; large-page devices have 64. 1110e8cc8bdSWilliam Juul * Default to something in the order of 5 to 10 blocks worth of chunks. 1120e8cc8bdSWilliam Juul */ 1130e8cc8bdSWilliam Juul #define YAFFS_WR_ATTEMPTS (5*64) 1140e8cc8bdSWilliam Juul 1150e8cc8bdSWilliam Juul /* Sequence numbers are used in YAFFS2 to determine block allocation order. 1160e8cc8bdSWilliam Juul * The range is limited slightly to help distinguish bad numbers from good. 1170e8cc8bdSWilliam Juul * This also allows us to perhaps in the future use special numbers for 1180e8cc8bdSWilliam Juul * special purposes. 119*753ac610SCharles Manning * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years, 1200e8cc8bdSWilliam Juul * and is a larger number than the lifetime of a 2GB device. 1210e8cc8bdSWilliam Juul */ 1220e8cc8bdSWilliam Juul #define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 123*753ac610SCharles Manning #define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xefffff00 124*753ac610SCharles Manning 125*753ac610SCharles Manning /* Special sequence number for bad block that failed to be marked bad */ 126*753ac610SCharles Manning #define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000 1270e8cc8bdSWilliam Juul 1280e8cc8bdSWilliam Juul /* ChunkCache is used for short read/write operations.*/ 129*753ac610SCharles Manning struct yaffs_cache { 130*753ac610SCharles Manning struct yaffs_obj *object; 131*753ac610SCharles Manning int chunk_id; 132*753ac610SCharles Manning int last_use; 1330e8cc8bdSWilliam Juul int dirty; 134*753ac610SCharles Manning int n_bytes; /* Only valid if the cache is dirty */ 1350e8cc8bdSWilliam Juul int locked; /* Can't push out or flush while locked. */ 136*753ac610SCharles Manning u8 *data; 137*753ac610SCharles Manning }; 1380e8cc8bdSWilliam Juul 139*753ac610SCharles Manning /* yaffs1 tags structures in RAM 140*753ac610SCharles Manning * NB This uses bitfield. Bitfields should not straddle a u32 boundary 141*753ac610SCharles Manning * otherwise the structure size will get blown out. 1420e8cc8bdSWilliam Juul */ 1430e8cc8bdSWilliam Juul 144*753ac610SCharles Manning struct yaffs_tags { 145*753ac610SCharles Manning unsigned chunk_id:20; 146*753ac610SCharles Manning unsigned serial_number:2; 147*753ac610SCharles Manning unsigned n_bytes_lsb:10; 148*753ac610SCharles Manning unsigned obj_id:18; 1490e8cc8bdSWilliam Juul unsigned ecc:12; 150*753ac610SCharles Manning unsigned n_bytes_msb:2; 151*753ac610SCharles Manning }; 1520e8cc8bdSWilliam Juul 153*753ac610SCharles Manning union yaffs_tags_union { 154*753ac610SCharles Manning struct yaffs_tags as_tags; 155*753ac610SCharles Manning u8 as_bytes[8]; 156*753ac610SCharles Manning }; 1570e8cc8bdSWilliam Juul 1580e8cc8bdSWilliam Juul 1590e8cc8bdSWilliam Juul /* Stuff used for extended tags in YAFFS2 */ 1600e8cc8bdSWilliam Juul 161*753ac610SCharles Manning enum yaffs_ecc_result { 1620e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_UNKNOWN, 1630e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_NO_ERROR, 1640e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_FIXED, 1650e8cc8bdSWilliam Juul YAFFS_ECC_RESULT_UNFIXED 166*753ac610SCharles Manning }; 1670e8cc8bdSWilliam Juul 168*753ac610SCharles Manning enum yaffs_obj_type { 1690e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_UNKNOWN, 1700e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_FILE, 1710e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_SYMLINK, 1720e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_DIRECTORY, 1730e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_HARDLINK, 1740e8cc8bdSWilliam Juul YAFFS_OBJECT_TYPE_SPECIAL 175*753ac610SCharles Manning }; 1760e8cc8bdSWilliam Juul 1770e8cc8bdSWilliam Juul #define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL 1780e8cc8bdSWilliam Juul 179*753ac610SCharles Manning struct yaffs_ext_tags { 180*753ac610SCharles Manning unsigned chunk_used; /* Status of the chunk: used or unused */ 181*753ac610SCharles Manning unsigned obj_id; /* If 0 this is not used */ 182*753ac610SCharles Manning unsigned chunk_id; /* If 0 this is a header, else a data chunk */ 183*753ac610SCharles Manning unsigned n_bytes; /* Only valid for data chunks */ 1840e8cc8bdSWilliam Juul 1850e8cc8bdSWilliam Juul /* The following stuff only has meaning when we read */ 186*753ac610SCharles Manning enum yaffs_ecc_result ecc_result; 187*753ac610SCharles Manning unsigned block_bad; 1880e8cc8bdSWilliam Juul 1890e8cc8bdSWilliam Juul /* YAFFS 1 stuff */ 190*753ac610SCharles Manning unsigned is_deleted; /* The chunk is marked deleted */ 191*753ac610SCharles Manning unsigned serial_number; /* Yaffs1 2-bit serial number */ 1920e8cc8bdSWilliam Juul 1930e8cc8bdSWilliam Juul /* YAFFS2 stuff */ 194*753ac610SCharles Manning unsigned seq_number; /* The sequence number of this block */ 1950e8cc8bdSWilliam Juul 1960e8cc8bdSWilliam Juul /* Extra info if this is an object header (YAFFS2 only) */ 1970e8cc8bdSWilliam Juul 198*753ac610SCharles Manning unsigned extra_available; /* Extra info available if not zero */ 199*753ac610SCharles Manning unsigned extra_parent_id; /* The parent object */ 200*753ac610SCharles Manning unsigned extra_is_shrink; /* Is it a shrink header? */ 201*753ac610SCharles Manning unsigned extra_shadows; /* Does this shadow another object? */ 2020e8cc8bdSWilliam Juul 203*753ac610SCharles Manning enum yaffs_obj_type extra_obj_type; /* What object type? */ 2040e8cc8bdSWilliam Juul 205*753ac610SCharles Manning loff_t extra_file_size; /* Length if it is a file */ 206*753ac610SCharles Manning unsigned extra_equiv_id; /* Equivalent object for a hard link */ 207*753ac610SCharles Manning }; 2080e8cc8bdSWilliam Juul 2090e8cc8bdSWilliam Juul /* Spare structure for YAFFS1 */ 210*753ac610SCharles Manning struct yaffs_spare { 211*753ac610SCharles Manning u8 tb0; 212*753ac610SCharles Manning u8 tb1; 213*753ac610SCharles Manning u8 tb2; 214*753ac610SCharles Manning u8 tb3; 215*753ac610SCharles Manning u8 page_status; /* set to 0 to delete the chunk */ 216*753ac610SCharles Manning u8 block_status; 217*753ac610SCharles Manning u8 tb4; 218*753ac610SCharles Manning u8 tb5; 219*753ac610SCharles Manning u8 ecc1[3]; 220*753ac610SCharles Manning u8 tb6; 221*753ac610SCharles Manning u8 tb7; 222*753ac610SCharles Manning u8 ecc2[3]; 223*753ac610SCharles Manning }; 2240e8cc8bdSWilliam Juul 2250e8cc8bdSWilliam Juul /*Special structure for passing through to mtd */ 226*753ac610SCharles Manning struct yaffs_nand_spare { 227*753ac610SCharles Manning struct yaffs_spare spare; 2280e8cc8bdSWilliam Juul int eccres1; 2290e8cc8bdSWilliam Juul int eccres2; 2300e8cc8bdSWilliam Juul }; 2310e8cc8bdSWilliam Juul 2320e8cc8bdSWilliam Juul /* Block data in RAM */ 2330e8cc8bdSWilliam Juul 234*753ac610SCharles Manning enum yaffs_block_state { 2350e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_UNKNOWN = 0, 2360e8cc8bdSWilliam Juul 2370e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_SCANNING, 238*753ac610SCharles Manning /* Being scanned */ 239*753ac610SCharles Manning 240*753ac610SCharles Manning YAFFS_BLOCK_STATE_NEEDS_SCAN, 241*753ac610SCharles Manning /* The block might have something on it (ie it is allocating or full, 242*753ac610SCharles Manning * perhaps empty) but it needs to be scanned to determine its true 243*753ac610SCharles Manning * state. 244*753ac610SCharles Manning * This state is only valid during scanning. 245*753ac610SCharles Manning * NB We tolerate empty because the pre-scanner might be incapable of 246*753ac610SCharles Manning * deciding 247*753ac610SCharles Manning * However, if this state is returned on a YAFFS2 device, 248*753ac610SCharles Manning * then we expect a sequence number 2490e8cc8bdSWilliam Juul */ 2500e8cc8bdSWilliam Juul 2510e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_EMPTY, 2520e8cc8bdSWilliam Juul /* This block is empty */ 2530e8cc8bdSWilliam Juul 2540e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_ALLOCATING, 2550e8cc8bdSWilliam Juul /* This block is partially allocated. 2560e8cc8bdSWilliam Juul * At least one page holds valid data. 2570e8cc8bdSWilliam Juul * This is the one currently being used for page 258*753ac610SCharles Manning * allocation. Should never be more than one of these. 259*753ac610SCharles Manning * If a block is only partially allocated at mount it is treated as 260*753ac610SCharles Manning * full. 2610e8cc8bdSWilliam Juul */ 2620e8cc8bdSWilliam Juul 2630e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_FULL, 2640e8cc8bdSWilliam Juul /* All the pages in this block have been allocated. 265*753ac610SCharles Manning * If a block was only partially allocated when mounted we treat 266*753ac610SCharles Manning * it as fully allocated. 2670e8cc8bdSWilliam Juul */ 2680e8cc8bdSWilliam Juul 2690e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_DIRTY, 270*753ac610SCharles Manning /* The block was full and now all chunks have been deleted. 2710e8cc8bdSWilliam Juul * Erase me, reuse me. 2720e8cc8bdSWilliam Juul */ 2730e8cc8bdSWilliam Juul 2740e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_CHECKPOINT, 275*753ac610SCharles Manning /* This block is assigned to holding checkpoint data. */ 2760e8cc8bdSWilliam Juul 2770e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_COLLECTING, 2780e8cc8bdSWilliam Juul /* This block is being garbage collected */ 2790e8cc8bdSWilliam Juul 2800e8cc8bdSWilliam Juul YAFFS_BLOCK_STATE_DEAD 2810e8cc8bdSWilliam Juul /* This block has failed and is not in use */ 282*753ac610SCharles Manning }; 2830e8cc8bdSWilliam Juul 2840e8cc8bdSWilliam Juul #define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) 2850e8cc8bdSWilliam Juul 286*753ac610SCharles Manning struct yaffs_block_info { 2870e8cc8bdSWilliam Juul 288*753ac610SCharles Manning int soft_del_pages:10; /* number of soft deleted pages */ 289*753ac610SCharles Manning int pages_in_use:10; /* number of pages in use */ 290*753ac610SCharles Manning unsigned block_state:4; /* One of the above block states. */ 291*753ac610SCharles Manning /* NB use unsigned because enum is sometimes 292*753ac610SCharles Manning * an int */ 293*753ac610SCharles Manning u32 needs_retiring:1; /* Data has failed on this block, */ 294*753ac610SCharles Manning /*need to get valid data off and retire*/ 295*753ac610SCharles Manning u32 skip_erased_check:1;/* Skip the erased check on this block */ 296*753ac610SCharles Manning u32 gc_prioritise:1; /* An ECC check or blank check has failed. 297*753ac610SCharles Manning Block should be prioritised for GC */ 298*753ac610SCharles Manning u32 chunk_error_strikes:3; /* How many times we've had ecc etc 299*753ac610SCharles Manning failures on this block and tried to reuse it */ 300*753ac610SCharles Manning u32 has_summary:1; /* The block has a summary */ 3010e8cc8bdSWilliam Juul 302*753ac610SCharles Manning u32 has_shrink_hdr:1; /* This block has at least one shrink header */ 303*753ac610SCharles Manning u32 seq_number; /* block sequence number for yaffs2 */ 3040e8cc8bdSWilliam Juul 305*753ac610SCharles Manning }; 3060e8cc8bdSWilliam Juul 3070e8cc8bdSWilliam Juul /* -------------------------- Object structure -------------------------------*/ 3080e8cc8bdSWilliam Juul /* This is the object structure as stored on NAND */ 3090e8cc8bdSWilliam Juul 310*753ac610SCharles Manning struct yaffs_obj_hdr { 311*753ac610SCharles Manning enum yaffs_obj_type type; 3120e8cc8bdSWilliam Juul 3130e8cc8bdSWilliam Juul /* Apply to everything */ 314*753ac610SCharles Manning int parent_obj_id; 315*753ac610SCharles Manning u16 sum_no_longer_used; /* checksum of name. No longer used */ 3160e8cc8bdSWilliam Juul YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; 3170e8cc8bdSWilliam Juul 318*753ac610SCharles Manning /* The following apply to all object types except for hard links */ 319*753ac610SCharles Manning u32 yst_mode; /* protection */ 3200e8cc8bdSWilliam Juul 321*753ac610SCharles Manning u32 yst_uid; 322*753ac610SCharles Manning u32 yst_gid; 323*753ac610SCharles Manning u32 yst_atime; 324*753ac610SCharles Manning u32 yst_mtime; 325*753ac610SCharles Manning u32 yst_ctime; 3260e8cc8bdSWilliam Juul 3270e8cc8bdSWilliam Juul /* File size applies to files only */ 328*753ac610SCharles Manning u32 file_size_low; 3290e8cc8bdSWilliam Juul 3300e8cc8bdSWilliam Juul /* Equivalent object id applies to hard links only. */ 331*753ac610SCharles Manning int equiv_id; 3320e8cc8bdSWilliam Juul 3330e8cc8bdSWilliam Juul /* Alias is for symlinks only. */ 3340e8cc8bdSWilliam Juul YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1]; 3350e8cc8bdSWilliam Juul 336*753ac610SCharles Manning u32 yst_rdev; /* stuff for block and char devices (major/min) */ 3370e8cc8bdSWilliam Juul 338*753ac610SCharles Manning u32 win_ctime[2]; 339*753ac610SCharles Manning u32 win_atime[2]; 340*753ac610SCharles Manning u32 win_mtime[2]; 3410e8cc8bdSWilliam Juul 342*753ac610SCharles Manning u32 inband_shadowed_obj_id; 343*753ac610SCharles Manning u32 inband_is_shrink; 3440e8cc8bdSWilliam Juul 345*753ac610SCharles Manning u32 file_size_high; 346*753ac610SCharles Manning u32 reserved[1]; 347*753ac610SCharles Manning int shadows_obj; /* This object header shadows the 348*753ac610SCharles Manning specified object if > 0 */ 3490e8cc8bdSWilliam Juul 350*753ac610SCharles Manning /* is_shrink applies to object headers written when wemake a hole. */ 351*753ac610SCharles Manning u32 is_shrink; 352*753ac610SCharles Manning 353*753ac610SCharles Manning }; 3540e8cc8bdSWilliam Juul 3550e8cc8bdSWilliam Juul /*--------------------------- Tnode -------------------------- */ 3560e8cc8bdSWilliam Juul 357*753ac610SCharles Manning struct yaffs_tnode { 358*753ac610SCharles Manning struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL]; 3590e8cc8bdSWilliam Juul }; 3600e8cc8bdSWilliam Juul 3610e8cc8bdSWilliam Juul /*------------------------ Object -----------------------------*/ 3620e8cc8bdSWilliam Juul /* An object can be one of: 3630e8cc8bdSWilliam Juul * - a directory (no data, has children links 3640e8cc8bdSWilliam Juul * - a regular file (data.... not prunes :->). 3650e8cc8bdSWilliam Juul * - a symlink [symbolic link] (the alias). 3660e8cc8bdSWilliam Juul * - a hard link 3670e8cc8bdSWilliam Juul */ 3680e8cc8bdSWilliam Juul 369*753ac610SCharles Manning struct yaffs_file_var { 370*753ac610SCharles Manning loff_t file_size; 371*753ac610SCharles Manning loff_t scanned_size; 372*753ac610SCharles Manning loff_t shrink_size; 373*753ac610SCharles Manning int top_level; 374*753ac610SCharles Manning struct yaffs_tnode *top; 375*753ac610SCharles Manning }; 3760e8cc8bdSWilliam Juul 377*753ac610SCharles Manning struct yaffs_dir_var { 3780e8cc8bdSWilliam Juul struct list_head children; /* list of child links */ 379*753ac610SCharles Manning struct list_head dirty; /* Entry for list of dirty directories */ 380*753ac610SCharles Manning }; 3810e8cc8bdSWilliam Juul 382*753ac610SCharles Manning struct yaffs_symlink_var { 3830e8cc8bdSWilliam Juul YCHAR *alias; 384*753ac610SCharles Manning }; 3850e8cc8bdSWilliam Juul 386*753ac610SCharles Manning struct yaffs_hardlink_var { 387*753ac610SCharles Manning struct yaffs_obj *equiv_obj; 388*753ac610SCharles Manning u32 equiv_id; 389*753ac610SCharles Manning }; 3900e8cc8bdSWilliam Juul 391*753ac610SCharles Manning union yaffs_obj_var { 392*753ac610SCharles Manning struct yaffs_file_var file_variant; 393*753ac610SCharles Manning struct yaffs_dir_var dir_variant; 394*753ac610SCharles Manning struct yaffs_symlink_var symlink_variant; 395*753ac610SCharles Manning struct yaffs_hardlink_var hardlink_variant; 396*753ac610SCharles Manning }; 3970e8cc8bdSWilliam Juul 398*753ac610SCharles Manning struct yaffs_obj { 399*753ac610SCharles Manning u8 deleted:1; /* This should only apply to unlinked files. */ 400*753ac610SCharles Manning u8 soft_del:1; /* it has also been soft deleted */ 401*753ac610SCharles Manning u8 unlinked:1; /* An unlinked file.*/ 402*753ac610SCharles Manning u8 fake:1; /* A fake object has no presence on NAND. */ 403*753ac610SCharles Manning u8 rename_allowed:1; /* Some objects cannot be renamed. */ 404*753ac610SCharles Manning u8 unlink_allowed:1; 405*753ac610SCharles Manning u8 dirty:1; /* the object needs to be written to flash */ 406*753ac610SCharles Manning u8 valid:1; /* When the file system is being loaded up, this 4070e8cc8bdSWilliam Juul * object might be created before the data 408*753ac610SCharles Manning * is available 409*753ac610SCharles Manning * ie. file data chunks encountered before 410*753ac610SCharles Manning * the header. 4110e8cc8bdSWilliam Juul */ 412*753ac610SCharles Manning u8 lazy_loaded:1; /* This object has been lazy loaded and 413*753ac610SCharles Manning * is missing some detail */ 4140e8cc8bdSWilliam Juul 415*753ac610SCharles Manning u8 defered_free:1; /* Object is removed from NAND, but is 416*753ac610SCharles Manning * still in the inode cache. 417*753ac610SCharles Manning * Free of object is defered. 4180e8cc8bdSWilliam Juul * until the inode is released. 4190e8cc8bdSWilliam Juul */ 420*753ac610SCharles Manning u8 being_created:1; /* This object is still being created 421*753ac610SCharles Manning * so skip some verification checks. */ 422*753ac610SCharles Manning u8 is_shadowed:1; /* This object is shadowed on the way 423*753ac610SCharles Manning * to being renamed. */ 4240e8cc8bdSWilliam Juul 425*753ac610SCharles Manning u8 xattr_known:1; /* We know if this has object has xattribs 426*753ac610SCharles Manning * or not. */ 427*753ac610SCharles Manning u8 has_xattr:1; /* This object has xattribs. 428*753ac610SCharles Manning * Only valid if xattr_known. */ 4290e8cc8bdSWilliam Juul 430*753ac610SCharles Manning u8 serial; /* serial number of chunk in NAND.*/ 431*753ac610SCharles Manning u16 sum; /* sum of the name to speed searching */ 4320e8cc8bdSWilliam Juul 433*753ac610SCharles Manning struct yaffs_dev *my_dev; /* The device I'm on */ 4340e8cc8bdSWilliam Juul 435*753ac610SCharles Manning struct list_head hash_link; /* list of objects in hash bucket */ 436*753ac610SCharles Manning 437*753ac610SCharles Manning struct list_head hard_links; /* hard linked object chain*/ 4380e8cc8bdSWilliam Juul 4390e8cc8bdSWilliam Juul /* directory structure stuff */ 4400e8cc8bdSWilliam Juul /* also used for linking up the free list */ 441*753ac610SCharles Manning struct yaffs_obj *parent; 4420e8cc8bdSWilliam Juul struct list_head siblings; 4430e8cc8bdSWilliam Juul 4440e8cc8bdSWilliam Juul /* Where's my object header in NAND? */ 445*753ac610SCharles Manning int hdr_chunk; 4460e8cc8bdSWilliam Juul 447*753ac610SCharles Manning int n_data_chunks; /* Number of data chunks for this file. */ 4480e8cc8bdSWilliam Juul 449*753ac610SCharles Manning u32 obj_id; /* the object id value */ 4500e8cc8bdSWilliam Juul 451*753ac610SCharles Manning u32 yst_mode; 4520e8cc8bdSWilliam Juul 453*753ac610SCharles Manning YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1]; 4540e8cc8bdSWilliam Juul 4550e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_WINCE 456*753ac610SCharles Manning u32 win_ctime[2]; 457*753ac610SCharles Manning u32 win_mtime[2]; 458*753ac610SCharles Manning u32 win_atime[2]; 4590e8cc8bdSWilliam Juul #else 460*753ac610SCharles Manning u32 yst_uid; 461*753ac610SCharles Manning u32 yst_gid; 462*753ac610SCharles Manning u32 yst_atime; 463*753ac610SCharles Manning u32 yst_mtime; 464*753ac610SCharles Manning u32 yst_ctime; 4650e8cc8bdSWilliam Juul #endif 4660e8cc8bdSWilliam Juul 467*753ac610SCharles Manning u32 yst_rdev; 4680e8cc8bdSWilliam Juul 469*753ac610SCharles Manning void *my_inode; 4700e8cc8bdSWilliam Juul 471*753ac610SCharles Manning enum yaffs_obj_type variant_type; 4720e8cc8bdSWilliam Juul 473*753ac610SCharles Manning union yaffs_obj_var variant; 4740e8cc8bdSWilliam Juul 4750e8cc8bdSWilliam Juul }; 4760e8cc8bdSWilliam Juul 477*753ac610SCharles Manning struct yaffs_obj_bucket { 4780e8cc8bdSWilliam Juul struct list_head list; 4790e8cc8bdSWilliam Juul int count; 480*753ac610SCharles Manning }; 4810e8cc8bdSWilliam Juul 482*753ac610SCharles Manning /* yaffs_checkpt_obj holds the definition of an object as dumped 4830e8cc8bdSWilliam Juul * by checkpointing. 4840e8cc8bdSWilliam Juul */ 4850e8cc8bdSWilliam Juul 486*753ac610SCharles Manning struct yaffs_checkpt_obj { 487*753ac610SCharles Manning int struct_type; 488*753ac610SCharles Manning u32 obj_id; 489*753ac610SCharles Manning u32 parent_id; 490*753ac610SCharles Manning int hdr_chunk; 491*753ac610SCharles Manning enum yaffs_obj_type variant_type:3; 492*753ac610SCharles Manning u8 deleted:1; 493*753ac610SCharles Manning u8 soft_del:1; 494*753ac610SCharles Manning u8 unlinked:1; 495*753ac610SCharles Manning u8 fake:1; 496*753ac610SCharles Manning u8 rename_allowed:1; 497*753ac610SCharles Manning u8 unlink_allowed:1; 498*753ac610SCharles Manning u8 serial; 499*753ac610SCharles Manning int n_data_chunks; 500*753ac610SCharles Manning loff_t size_or_equiv_obj; 501*753ac610SCharles Manning }; 5020e8cc8bdSWilliam Juul 5030e8cc8bdSWilliam Juul /*--------------------- Temporary buffers ---------------- 5040e8cc8bdSWilliam Juul * 505*753ac610SCharles Manning * These are chunk-sized working buffers. Each device has a few. 5060e8cc8bdSWilliam Juul */ 5070e8cc8bdSWilliam Juul 508*753ac610SCharles Manning struct yaffs_buffer { 509*753ac610SCharles Manning u8 *buffer; 510*753ac610SCharles Manning int in_use; 511*753ac610SCharles Manning }; 5120e8cc8bdSWilliam Juul 5130e8cc8bdSWilliam Juul /*----------------- Device ---------------------------------*/ 5140e8cc8bdSWilliam Juul 515*753ac610SCharles Manning struct yaffs_param { 516*753ac610SCharles Manning const YCHAR *name; 5170e8cc8bdSWilliam Juul 518*753ac610SCharles Manning /* 519*753ac610SCharles Manning * Entry parameters set up way early. Yaffs sets up the rest. 520*753ac610SCharles Manning * The structure should be zeroed out before use so that unused 521*753ac610SCharles Manning * and defualt values are zero. 5220e8cc8bdSWilliam Juul */ 5230e8cc8bdSWilliam Juul 524*753ac610SCharles Manning int inband_tags; /* Use unband tags */ 525*753ac610SCharles Manning u32 total_bytes_per_chunk; /* Should be >= 512, does not need to 526*753ac610SCharles Manning be a power of 2 */ 527*753ac610SCharles Manning int chunks_per_block; /* does not need to be a power of 2 */ 528*753ac610SCharles Manning int spare_bytes_per_chunk; /* spare area size */ 529*753ac610SCharles Manning int start_block; /* Start block we're allowed to use */ 530*753ac610SCharles Manning int end_block; /* End block we're allowed to use */ 531*753ac610SCharles Manning int n_reserved_blocks; /* Tuneable so that we can reduce 532*753ac610SCharles Manning * reserved blocks on NOR and RAM. */ 5330e8cc8bdSWilliam Juul 534*753ac610SCharles Manning int n_caches; /* If <= 0, then short op caching is disabled, 535*753ac610SCharles Manning * else the number of short op caches. 5360e8cc8bdSWilliam Juul */ 537*753ac610SCharles Manning int use_nand_ecc; /* Flag to decide whether or not to use 538*753ac610SCharles Manning * NAND driver ECC on data (yaffs1) */ 539*753ac610SCharles Manning int tags_9bytes; /* Use 9 byte tags */ 540*753ac610SCharles Manning int no_tags_ecc; /* Flag to decide whether or not to do ECC 541*753ac610SCharles Manning * on packed tags (yaffs2) */ 542*753ac610SCharles Manning 543*753ac610SCharles Manning int is_yaffs2; /* Use yaffs2 mode on this device */ 544*753ac610SCharles Manning 545*753ac610SCharles Manning int empty_lost_n_found; /* Auto-empty lost+found directory on mount */ 546*753ac610SCharles Manning 547*753ac610SCharles Manning int refresh_period; /* How often to check for a block refresh */ 548*753ac610SCharles Manning 549*753ac610SCharles Manning /* Checkpoint control. Can be set before or after initialisation */ 550*753ac610SCharles Manning u8 skip_checkpt_rd; 551*753ac610SCharles Manning u8 skip_checkpt_wr; 552*753ac610SCharles Manning 553*753ac610SCharles Manning int enable_xattr; /* Enable xattribs */ 5540e8cc8bdSWilliam Juul 5550e8cc8bdSWilliam Juul /* NAND access functions (Must be set before calling YAFFS) */ 5560e8cc8bdSWilliam Juul 557*753ac610SCharles Manning int (*write_chunk_fn) (struct yaffs_dev *dev, 558*753ac610SCharles Manning int nand_chunk, const u8 *data, 559*753ac610SCharles Manning const struct yaffs_spare *spare); 560*753ac610SCharles Manning int (*read_chunk_fn) (struct yaffs_dev *dev, 561*753ac610SCharles Manning int nand_chunk, u8 *data, 562*753ac610SCharles Manning struct yaffs_spare *spare); 563*753ac610SCharles Manning int (*erase_fn) (struct yaffs_dev *dev, int flash_block); 564*753ac610SCharles Manning int (*initialise_flash_fn) (struct yaffs_dev *dev); 565*753ac610SCharles Manning int (*deinitialise_flash_fn) (struct yaffs_dev *dev); 5660e8cc8bdSWilliam Juul 567*753ac610SCharles Manning /* yaffs2 mode functions */ 568*753ac610SCharles Manning int (*write_chunk_tags_fn) (struct yaffs_dev *dev, 569*753ac610SCharles Manning int nand_chunk, const u8 *data, 570*753ac610SCharles Manning const struct yaffs_ext_tags *tags); 571*753ac610SCharles Manning int (*read_chunk_tags_fn) (struct yaffs_dev *dev, 572*753ac610SCharles Manning int nand_chunk, u8 *data, 573*753ac610SCharles Manning struct yaffs_ext_tags *tags); 574*753ac610SCharles Manning int (*bad_block_fn) (struct yaffs_dev *dev, int block_no); 575*753ac610SCharles Manning int (*query_block_fn) (struct yaffs_dev *dev, int block_no, 576*753ac610SCharles Manning enum yaffs_block_state *state, 577*753ac610SCharles Manning u32 *seq_number); 5780e8cc8bdSWilliam Juul 579*753ac610SCharles Manning /* The remove_obj_fn function must be supplied by OS flavours that 580*753ac610SCharles Manning * need it. 581*753ac610SCharles Manning * yaffs direct uses it to implement the faster readdir. 582*753ac610SCharles Manning * Linux uses it to protect the directory during unlocking. 5830e8cc8bdSWilliam Juul */ 584*753ac610SCharles Manning void (*remove_obj_fn) (struct yaffs_obj *obj); 5850e8cc8bdSWilliam Juul 586*753ac610SCharles Manning /* Callback to mark the superblock dirty */ 587*753ac610SCharles Manning void (*sb_dirty_fn) (struct yaffs_dev *dev); 5880e8cc8bdSWilliam Juul 589*753ac610SCharles Manning /* Callback to control garbage collection. */ 590*753ac610SCharles Manning unsigned (*gc_control) (struct yaffs_dev *dev); 5910e8cc8bdSWilliam Juul 592*753ac610SCharles Manning /* Debug control flags. Don't use unless you know what you're doing */ 593*753ac610SCharles Manning int use_header_file_size; /* Flag to determine if we should use 594*753ac610SCharles Manning * file sizes from the header */ 595*753ac610SCharles Manning int disable_lazy_load; /* Disable lazy loading on this device */ 596*753ac610SCharles Manning int wide_tnodes_disabled; /* Set to disable wide tnodes */ 597*753ac610SCharles Manning int disable_soft_del; /* yaffs 1 only: Set to disable the use of 598*753ac610SCharles Manning * softdeletion. */ 5990e8cc8bdSWilliam Juul 600*753ac610SCharles Manning int defered_dir_update; /* Set to defer directory updates */ 6010e8cc8bdSWilliam Juul 602*753ac610SCharles Manning #ifdef CONFIG_YAFFS_AUTO_UNICODE 603*753ac610SCharles Manning int auto_unicode; 604*753ac610SCharles Manning #endif 605*753ac610SCharles Manning int always_check_erased; /* Force chunk erased check always on */ 606*753ac610SCharles Manning 607*753ac610SCharles Manning int disable_summary; 608*753ac610SCharles Manning 609*753ac610SCharles Manning int max_objects; /* 610*753ac610SCharles Manning * Set to limit the number of objects created. 611*753ac610SCharles Manning * 0 = no limit. 612*753ac610SCharles Manning */ 613*753ac610SCharles Manning }; 614*753ac610SCharles Manning 615*753ac610SCharles Manning struct yaffs_dev { 616*753ac610SCharles Manning struct yaffs_param param; 617*753ac610SCharles Manning 618*753ac610SCharles Manning /* Context storage. Holds extra OS specific data for this device */ 619*753ac610SCharles Manning 620*753ac610SCharles Manning void *os_context; 621*753ac610SCharles Manning void *driver_context; 622*753ac610SCharles Manning 623*753ac610SCharles Manning struct list_head dev_list; 6240e8cc8bdSWilliam Juul 6250e8cc8bdSWilliam Juul /* Runtime parameters. Set up by YAFFS. */ 626*753ac610SCharles Manning int data_bytes_per_chunk; 6270e8cc8bdSWilliam Juul 628*753ac610SCharles Manning /* Non-wide tnode stuff */ 629*753ac610SCharles Manning u16 chunk_grp_bits; /* Number of bits that need to be resolved if 630*753ac610SCharles Manning * the tnodes are not wide enough. 631*753ac610SCharles Manning */ 632*753ac610SCharles Manning u16 chunk_grp_size; /* == 2^^chunk_grp_bits */ 6330e8cc8bdSWilliam Juul 6340e8cc8bdSWilliam Juul /* Stuff to support wide tnodes */ 635*753ac610SCharles Manning u32 tnode_width; 636*753ac610SCharles Manning u32 tnode_mask; 637*753ac610SCharles Manning u32 tnode_size; 6380e8cc8bdSWilliam Juul 639*753ac610SCharles Manning /* Stuff for figuring out file offset to chunk conversions */ 640*753ac610SCharles Manning u32 chunk_shift; /* Shift value */ 641*753ac610SCharles Manning u32 chunk_div; /* Divisor after shifting: 1 for 2^n sizes */ 642*753ac610SCharles Manning u32 chunk_mask; /* Mask to use for power-of-2 case */ 6430e8cc8bdSWilliam Juul 644*753ac610SCharles Manning int is_mounted; 645*753ac610SCharles Manning int read_only; 646*753ac610SCharles Manning int is_checkpointed; 6470e8cc8bdSWilliam Juul 6480e8cc8bdSWilliam Juul /* Stuff to support block offsetting to support start block zero */ 649*753ac610SCharles Manning int internal_start_block; 650*753ac610SCharles Manning int internal_end_block; 651*753ac610SCharles Manning int block_offset; 652*753ac610SCharles Manning int chunk_offset; 6530e8cc8bdSWilliam Juul 6540e8cc8bdSWilliam Juul /* Runtime checkpointing stuff */ 655*753ac610SCharles Manning int checkpt_page_seq; /* running sequence number of checkpt pages */ 656*753ac610SCharles Manning int checkpt_byte_count; 657*753ac610SCharles Manning int checkpt_byte_offs; 658*753ac610SCharles Manning u8 *checkpt_buffer; 659*753ac610SCharles Manning int checkpt_open_write; 660*753ac610SCharles Manning int blocks_in_checkpt; 661*753ac610SCharles Manning int checkpt_cur_chunk; 662*753ac610SCharles Manning int checkpt_cur_block; 663*753ac610SCharles Manning int checkpt_next_block; 664*753ac610SCharles Manning int *checkpt_block_list; 665*753ac610SCharles Manning int checkpt_max_blocks; 666*753ac610SCharles Manning u32 checkpt_sum; 667*753ac610SCharles Manning u32 checkpt_xor; 668*753ac610SCharles Manning 669*753ac610SCharles Manning int checkpoint_blocks_required; /* Number of blocks needed to store 670*753ac610SCharles Manning * current checkpoint set */ 6710e8cc8bdSWilliam Juul 6720e8cc8bdSWilliam Juul /* Block Info */ 673*753ac610SCharles Manning struct yaffs_block_info *block_info; 674*753ac610SCharles Manning u8 *chunk_bits; /* bitmap of chunks in use */ 675*753ac610SCharles Manning unsigned block_info_alt:1; /* allocated using alternative alloc */ 676*753ac610SCharles Manning unsigned chunk_bits_alt:1; /* allocated using alternative alloc */ 677*753ac610SCharles Manning int chunk_bit_stride; /* Number of bytes of chunk_bits per block. 678*753ac610SCharles Manning * Must be consistent with chunks_per_block. 6790e8cc8bdSWilliam Juul */ 6800e8cc8bdSWilliam Juul 681*753ac610SCharles Manning int n_erased_blocks; 682*753ac610SCharles Manning int alloc_block; /* Current block being allocated off */ 683*753ac610SCharles Manning u32 alloc_page; 684*753ac610SCharles Manning int alloc_block_finder; /* Used to search for next allocation block */ 6850e8cc8bdSWilliam Juul 686*753ac610SCharles Manning /* Object and Tnode memory management */ 687*753ac610SCharles Manning void *allocator; 688*753ac610SCharles Manning int n_obj; 689*753ac610SCharles Manning int n_tnodes; 6900e8cc8bdSWilliam Juul 691*753ac610SCharles Manning int n_hardlinks; 6920e8cc8bdSWilliam Juul 693*753ac610SCharles Manning struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS]; 694*753ac610SCharles Manning u32 bucket_finder; 6950e8cc8bdSWilliam Juul 696*753ac610SCharles Manning int n_free_chunks; 6970e8cc8bdSWilliam Juul 698*753ac610SCharles Manning /* Garbage collection control */ 699*753ac610SCharles Manning u32 *gc_cleanup_list; /* objects to delete at the end of a GC. */ 700*753ac610SCharles Manning u32 n_clean_ups; 7010e8cc8bdSWilliam Juul 702*753ac610SCharles Manning unsigned has_pending_prioritised_gc; /* We think this device might 703*753ac610SCharles Manning have pending prioritised gcs */ 704*753ac610SCharles Manning unsigned gc_disable; 705*753ac610SCharles Manning unsigned gc_block_finder; 706*753ac610SCharles Manning unsigned gc_dirtiest; 707*753ac610SCharles Manning unsigned gc_pages_in_use; 708*753ac610SCharles Manning unsigned gc_not_done; 709*753ac610SCharles Manning unsigned gc_block; 710*753ac610SCharles Manning unsigned gc_chunk; 711*753ac610SCharles Manning unsigned gc_skip; 712*753ac610SCharles Manning struct yaffs_summary_tags *gc_sum_tags; 7130e8cc8bdSWilliam Juul 7140e8cc8bdSWilliam Juul /* Special directories */ 715*753ac610SCharles Manning struct yaffs_obj *root_dir; 716*753ac610SCharles Manning struct yaffs_obj *lost_n_found; 7170e8cc8bdSWilliam Juul 718*753ac610SCharles Manning int buffered_block; /* Which block is buffered here? */ 719*753ac610SCharles Manning int doing_buffered_block_rewrite; 7200e8cc8bdSWilliam Juul 721*753ac610SCharles Manning struct yaffs_cache *cache; 722*753ac610SCharles Manning int cache_last_use; 7230e8cc8bdSWilliam Juul 7240e8cc8bdSWilliam Juul /* Stuff for background deletion and unlinked files. */ 725*753ac610SCharles Manning struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted 726*753ac610SCharles Manning files live. */ 727*753ac610SCharles Manning struct yaffs_obj *del_dir; /* Directory where deleted objects are 728*753ac610SCharles Manning sent to disappear. */ 729*753ac610SCharles Manning struct yaffs_obj *unlinked_deletion; /* Current file being 730*753ac610SCharles Manning background deleted. */ 731*753ac610SCharles Manning int n_deleted_files; /* Count of files awaiting deletion; */ 732*753ac610SCharles Manning int n_unlinked_files; /* Count of unlinked files. */ 733*753ac610SCharles Manning int n_bg_deletions; /* Count of background deletions. */ 7340e8cc8bdSWilliam Juul 735*753ac610SCharles Manning /* Temporary buffer management */ 736*753ac610SCharles Manning struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS]; 737*753ac610SCharles Manning int max_temp; 738*753ac610SCharles Manning int temp_in_use; 739*753ac610SCharles Manning int unmanaged_buffer_allocs; 740*753ac610SCharles Manning int unmanaged_buffer_deallocs; 7410e8cc8bdSWilliam Juul 7420e8cc8bdSWilliam Juul /* yaffs2 runtime stuff */ 743*753ac610SCharles Manning unsigned seq_number; /* Sequence number of currently 744*753ac610SCharles Manning allocating block */ 745*753ac610SCharles Manning unsigned oldest_dirty_seq; 746*753ac610SCharles Manning unsigned oldest_dirty_block; 747*753ac610SCharles Manning 748*753ac610SCharles Manning /* Block refreshing */ 749*753ac610SCharles Manning int refresh_skip; /* A skip down counter. 750*753ac610SCharles Manning * Refresh happens when this gets to zero. */ 751*753ac610SCharles Manning 752*753ac610SCharles Manning /* Dirty directory handling */ 753*753ac610SCharles Manning struct list_head dirty_dirs; /* List of dirty directories */ 754*753ac610SCharles Manning 755*753ac610SCharles Manning /* Summary */ 756*753ac610SCharles Manning int chunks_per_summary; 757*753ac610SCharles Manning struct yaffs_summary_tags *sum_tags; 758*753ac610SCharles Manning 759*753ac610SCharles Manning /* Statistics */ 760*753ac610SCharles Manning u32 n_page_writes; 761*753ac610SCharles Manning u32 n_page_reads; 762*753ac610SCharles Manning u32 n_erasures; 763*753ac610SCharles Manning u32 n_erase_failures; 764*753ac610SCharles Manning u32 n_gc_copies; 765*753ac610SCharles Manning u32 all_gcs; 766*753ac610SCharles Manning u32 passive_gc_count; 767*753ac610SCharles Manning u32 oldest_dirty_gc_count; 768*753ac610SCharles Manning u32 n_gc_blocks; 769*753ac610SCharles Manning u32 bg_gcs; 770*753ac610SCharles Manning u32 n_retried_writes; 771*753ac610SCharles Manning u32 n_retired_blocks; 772*753ac610SCharles Manning u32 n_ecc_fixed; 773*753ac610SCharles Manning u32 n_ecc_unfixed; 774*753ac610SCharles Manning u32 n_tags_ecc_fixed; 775*753ac610SCharles Manning u32 n_tags_ecc_unfixed; 776*753ac610SCharles Manning u32 n_deletions; 777*753ac610SCharles Manning u32 n_unmarked_deletions; 778*753ac610SCharles Manning u32 refresh_count; 779*753ac610SCharles Manning u32 cache_hits; 780*753ac610SCharles Manning u32 tags_used; 781*753ac610SCharles Manning u32 summary_used; 7820e8cc8bdSWilliam Juul 7830e8cc8bdSWilliam Juul }; 7840e8cc8bdSWilliam Juul 785*753ac610SCharles Manning /* The CheckpointDevice structure holds the device information that changes 786*753ac610SCharles Manning *at runtime and must be preserved over unmount/mount cycles. 7870e8cc8bdSWilliam Juul */ 788*753ac610SCharles Manning struct yaffs_checkpt_dev { 789*753ac610SCharles Manning int struct_type; 790*753ac610SCharles Manning int n_erased_blocks; 791*753ac610SCharles Manning int alloc_block; /* Current block being allocated off */ 792*753ac610SCharles Manning u32 alloc_page; 793*753ac610SCharles Manning int n_free_chunks; 7940e8cc8bdSWilliam Juul 795*753ac610SCharles Manning int n_deleted_files; /* Count of files awaiting deletion; */ 796*753ac610SCharles Manning int n_unlinked_files; /* Count of unlinked files. */ 797*753ac610SCharles Manning int n_bg_deletions; /* Count of background deletions. */ 7980e8cc8bdSWilliam Juul 7990e8cc8bdSWilliam Juul /* yaffs2 runtime stuff */ 800*753ac610SCharles Manning unsigned seq_number; /* Sequence number of currently 801*753ac610SCharles Manning * allocating block */ 8020e8cc8bdSWilliam Juul 803*753ac610SCharles Manning }; 8040e8cc8bdSWilliam Juul 805*753ac610SCharles Manning struct yaffs_checkpt_validity { 806*753ac610SCharles Manning int struct_type; 807*753ac610SCharles Manning u32 magic; 808*753ac610SCharles Manning u32 version; 809*753ac610SCharles Manning u32 head; 810*753ac610SCharles Manning }; 8110e8cc8bdSWilliam Juul 812*753ac610SCharles Manning struct yaffs_shadow_fixer { 813*753ac610SCharles Manning int obj_id; 814*753ac610SCharles Manning int shadowed_id; 815*753ac610SCharles Manning struct yaffs_shadow_fixer *next; 816*753ac610SCharles Manning }; 8170e8cc8bdSWilliam Juul 818*753ac610SCharles Manning /* Structure for doing xattr modifications */ 819*753ac610SCharles Manning struct yaffs_xattr_mod { 820*753ac610SCharles Manning int set; /* If 0 then this is a deletion */ 821*753ac610SCharles Manning const YCHAR *name; 822*753ac610SCharles Manning const void *data; 823*753ac610SCharles Manning int size; 824*753ac610SCharles Manning int flags; 825*753ac610SCharles Manning int result; 826*753ac610SCharles Manning }; 8270e8cc8bdSWilliam Juul 8280e8cc8bdSWilliam Juul /*----------------------- YAFFS Functions -----------------------*/ 8290e8cc8bdSWilliam Juul 830*753ac610SCharles Manning int yaffs_guts_initialise(struct yaffs_dev *dev); 831*753ac610SCharles Manning void yaffs_deinitialise(struct yaffs_dev *dev); 8320e8cc8bdSWilliam Juul 833*753ac610SCharles Manning int yaffs_get_n_free_chunks(struct yaffs_dev *dev); 8340e8cc8bdSWilliam Juul 835*753ac610SCharles Manning int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name, 836*753ac610SCharles Manning struct yaffs_obj *new_dir, const YCHAR * new_name); 8370e8cc8bdSWilliam Juul 838*753ac610SCharles Manning int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name); 839*753ac610SCharles Manning int yaffs_del_obj(struct yaffs_obj *obj); 8400e8cc8bdSWilliam Juul 841*753ac610SCharles Manning int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size); 842*753ac610SCharles Manning loff_t yaffs_get_obj_length(struct yaffs_obj *obj); 843*753ac610SCharles Manning int yaffs_get_obj_inode(struct yaffs_obj *obj); 844*753ac610SCharles Manning unsigned yaffs_get_obj_type(struct yaffs_obj *obj); 845*753ac610SCharles Manning int yaffs_get_obj_link_count(struct yaffs_obj *obj); 8460e8cc8bdSWilliam Juul 8470e8cc8bdSWilliam Juul /* File operations */ 848*753ac610SCharles Manning int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset, 849*753ac610SCharles Manning int n_bytes); 850*753ac610SCharles Manning int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset, 851*753ac610SCharles Manning int n_bytes, int write_trhrough); 852*753ac610SCharles Manning int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size); 8530e8cc8bdSWilliam Juul 854*753ac610SCharles Manning struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent, 855*753ac610SCharles Manning const YCHAR *name, u32 mode, u32 uid, 856*753ac610SCharles Manning u32 gid); 857*753ac610SCharles Manning 858*753ac610SCharles Manning int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync); 8590e8cc8bdSWilliam Juul 8600e8cc8bdSWilliam Juul /* Flushing and checkpointing */ 861*753ac610SCharles Manning void yaffs_flush_whole_cache(struct yaffs_dev *dev); 8620e8cc8bdSWilliam Juul 863*753ac610SCharles Manning int yaffs_checkpoint_save(struct yaffs_dev *dev); 864*753ac610SCharles Manning int yaffs_checkpoint_restore(struct yaffs_dev *dev); 8650e8cc8bdSWilliam Juul 8660e8cc8bdSWilliam Juul /* Directory operations */ 867*753ac610SCharles Manning struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name, 868*753ac610SCharles Manning u32 mode, u32 uid, u32 gid); 869*753ac610SCharles Manning struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir, 870*753ac610SCharles Manning const YCHAR *name); 871*753ac610SCharles Manning struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number); 8720e8cc8bdSWilliam Juul 8730e8cc8bdSWilliam Juul /* Link operations */ 874*753ac610SCharles Manning struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name, 875*753ac610SCharles Manning struct yaffs_obj *equiv_obj); 8760e8cc8bdSWilliam Juul 877*753ac610SCharles Manning struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj); 8780e8cc8bdSWilliam Juul 8790e8cc8bdSWilliam Juul /* Symlink operations */ 880*753ac610SCharles Manning struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent, 881*753ac610SCharles Manning const YCHAR *name, u32 mode, u32 uid, 882*753ac610SCharles Manning u32 gid, const YCHAR *alias); 883*753ac610SCharles Manning YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj); 8840e8cc8bdSWilliam Juul 8850e8cc8bdSWilliam Juul /* Special inodes (fifos, sockets and devices) */ 886*753ac610SCharles Manning struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent, 887*753ac610SCharles Manning const YCHAR *name, u32 mode, u32 uid, 888*753ac610SCharles Manning u32 gid, u32 rdev); 889*753ac610SCharles Manning 890*753ac610SCharles Manning int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name, 891*753ac610SCharles Manning const void *value, int size, int flags); 892*753ac610SCharles Manning int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value, 893*753ac610SCharles Manning int size); 894*753ac610SCharles Manning int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size); 895*753ac610SCharles Manning int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name); 8960e8cc8bdSWilliam Juul 8970e8cc8bdSWilliam Juul /* Special directories */ 898*753ac610SCharles Manning struct yaffs_obj *yaffs_root(struct yaffs_dev *dev); 899*753ac610SCharles Manning struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev); 9000e8cc8bdSWilliam Juul 901*753ac610SCharles Manning void yaffs_handle_defered_free(struct yaffs_obj *obj); 9020e8cc8bdSWilliam Juul 903*753ac610SCharles Manning void yaffs_update_dirty_dirs(struct yaffs_dev *dev); 904*753ac610SCharles Manning 905*753ac610SCharles Manning int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency); 9060e8cc8bdSWilliam Juul 9070e8cc8bdSWilliam Juul /* Debug dump */ 908*753ac610SCharles Manning int yaffs_dump_obj(struct yaffs_obj *obj); 9090e8cc8bdSWilliam Juul 910*753ac610SCharles Manning void yaffs_guts_test(struct yaffs_dev *dev); 9110e8cc8bdSWilliam Juul 912*753ac610SCharles Manning /* A few useful functions to be used within the core files*/ 913*753ac610SCharles Manning void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, 914*753ac610SCharles Manning int lyn); 915*753ac610SCharles Manning int yaffs_check_ff(u8 *buffer, int n_bytes); 916*753ac610SCharles Manning void yaffs_handle_chunk_error(struct yaffs_dev *dev, 917*753ac610SCharles Manning struct yaffs_block_info *bi); 918*753ac610SCharles Manning 919*753ac610SCharles Manning u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev); 920*753ac610SCharles Manning void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer); 921*753ac610SCharles Manning 922*753ac610SCharles Manning struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev, 923*753ac610SCharles Manning int number, 924*753ac610SCharles Manning enum yaffs_obj_type type); 925*753ac610SCharles Manning int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk, 926*753ac610SCharles Manning int nand_chunk, int in_scan); 927*753ac610SCharles Manning void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name); 928*753ac610SCharles Manning void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, 929*753ac610SCharles Manning const struct yaffs_obj_hdr *oh); 930*753ac610SCharles Manning void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj); 931*753ac610SCharles Manning YCHAR *yaffs_clone_str(const YCHAR *str); 932*753ac610SCharles Manning void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list); 933*753ac610SCharles Manning void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no); 934*753ac610SCharles Manning int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, 935*753ac610SCharles Manning int force, int is_shrink, int shadows, 936*753ac610SCharles Manning struct yaffs_xattr_mod *xop); 937*753ac610SCharles Manning void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id, 938*753ac610SCharles Manning int backward_scanning); 939*753ac610SCharles Manning int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks); 940*753ac610SCharles Manning struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev); 941*753ac610SCharles Manning struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev, 942*753ac610SCharles Manning struct yaffs_file_var *file_struct, 943*753ac610SCharles Manning u32 chunk_id, 944*753ac610SCharles Manning struct yaffs_tnode *passed_tn); 945*753ac610SCharles Manning 946*753ac610SCharles Manning int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, 947*753ac610SCharles Manning int n_bytes, int write_trhrough); 948*753ac610SCharles Manning void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size); 949*753ac610SCharles Manning void yaffs_skip_rest_of_block(struct yaffs_dev *dev); 950*753ac610SCharles Manning 951*753ac610SCharles Manning int yaffs_count_free_chunks(struct yaffs_dev *dev); 952*753ac610SCharles Manning 953*753ac610SCharles Manning struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev, 954*753ac610SCharles Manning struct yaffs_file_var *file_struct, 955*753ac610SCharles Manning u32 chunk_id); 956*753ac610SCharles Manning 957*753ac610SCharles Manning u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, 958*753ac610SCharles Manning unsigned pos); 959*753ac610SCharles Manning 960*753ac610SCharles Manning int yaffs_is_non_empty_dir(struct yaffs_obj *obj); 961*753ac610SCharles Manning 962*753ac610SCharles Manning void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr, 963*753ac610SCharles Manning int *chunk_out, u32 *offset_out); 964*753ac610SCharles Manning /* 965*753ac610SCharles Manning * Marshalling functions to get loff_t file sizes into aand out of 966*753ac610SCharles Manning * object headers. 967*753ac610SCharles Manning */ 968*753ac610SCharles Manning void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize); 969*753ac610SCharles Manning loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh); 970*753ac610SCharles Manning loff_t yaffs_max_file_size(struct yaffs_dev *dev); 971*753ac610SCharles Manning 9720e8cc8bdSWilliam Juul 9730e8cc8bdSWilliam Juul #endif 974