*** empty log message ***
[yaffs/.git] / yaffs_guts.h
1 /*\r
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. \r
3  * yaffs_guts.h: Configuration etc for yaffs_guts\r
4  *\r
5  * Copyright (C) 2002 Aleph One Ltd.\r
6  *   for Toby Churchill Ltd and Brightstar Engineering\r
7  *\r
8  * Created by Charles Manning <charles@aleph1.co.uk>\r
9  *\r
10  * This program is free software; you can redistribute it and/or modify\r
11  * it under the terms of the GNU General Public License version 2 as\r
12  * published by the Free Software Foundation.\r
13  *\r
14  */\r
15 \r
16 #ifndef __YAFFS_GUTS_H__\r
17 #define __YAFFS_GUTS_H__\r
18 \r
19 #include "devextras.h"\r
20 \r
21 \r
22 #define YAFFS_OK        1\r
23 #define YAFFS_FAIL  0\r
24 \r
25 // Y=0x59, A=0x41, S=0x53\r
26 #define YAFFS_MAGIC                                     0x5941FF53\r
27 \r
28 #define YAFFS_NTNODES_LEVEL0            16\r
29 #define YAFFS_TNODES_LEVEL0_BITS        4\r
30 #define YAFFS_TNODES_LEVEL0_MASK        0xf\r
31 \r
32 #define YAFFS_NTNODES_INTERNAL          (YAFFS_NTNODES_LEVEL0 / 2)\r
33 #define YAFFS_TNODES_INTERNAL_BITS      (YAFFS_TNODES_LEVEL0_BITS - 1)\r
34 #define YAFFS_TNODES_INTERNAL_MASK      0x7\r
35 #define YAFFS_TNODES_MAX_LEVEL          6\r
36                 \r
37 #define YAFFS_BYTES_PER_CHUNK           512\r
38 #define YAFFS_CHUNK_SIZE_SHIFT          9\r
39 \r
40 #define YAFFS_BYTES_PER_SPARE           16\r
41 \r
42 #define YAFFS_CHUNKS_PER_BLOCK          32\r
43 #define YAFFS_BYTES_PER_BLOCK           (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)\r
44 \r
45 #define YAFFS_MAX_CHUNK_ID                      0x000FFFFF\r
46 \r
47 #define YAFFS_UNUSED_OBJECT_ID          0x0003FFFF\r
48 \r
49 #define YAFFS_ALLOCATION_NOBJECTS       100\r
50 #define YAFFS_ALLOCATION_NTNODES        100\r
51 #define YAFFS_ALLOCATION_NLINKS         100\r
52 \r
53 #define YAFFS_NOBJECT_BUCKETS           256\r
54 \r
55 \r
56 #define YAFFS_RESERVED_BLOCKS           5\r
57 \r
58 #define YAFFS_OBJECT_SPACE                      0x40000\r
59 #define YAFFS_MAX_NAME_LENGTH           255\r
60 \r
61 #define YAFFS_MAX_ALIAS_LENGTH          159\r
62 \r
63 #define YAFFS_OBJECTID_ROOT                     1\r
64 #define YAFFS_OBJECTID_LOSTNFOUND       2\r
65 \r
66 // Tags structures in RAM\r
67 // NB This uses bitfield. Bitfields should not stradle a u32 boundary otherwise\r
68 // the structure size will get blown out.\r
69 \r
70 typedef struct\r
71 {\r
72     unsigned chunkId:20;\r
73     unsigned serialNumber:2;\r
74     unsigned byteCount:10;\r
75     unsigned objectId:18;\r
76     unsigned ecc:12;\r
77     unsigned unusedStuff:2;\r
78 } yaffs_Tags;\r
79 \r
80 typedef union\r
81 {\r
82     yaffs_Tags asTags;\r
83     __u8       asBytes[8];\r
84 } yaffs_TagsUnion;\r
85 \r
86 \r
87 // Spare structure\r
88 typedef struct\r
89 {\r
90     __u8  tagByte0;\r
91     __u8  tagByte1;\r
92     __u8  tagByte2;\r
93     __u8  tagByte3;\r
94     __u8  pageStatus; // Currently unused, but sort of set aside to distinguish\r
95                                   // unused - vs- used -vs- deleted chunks. We achieve this by\r
96                                           // using the objectId tags.\r
97     __u8  blockStatus;\r
98     __u8  tagByte4;\r
99     __u8  tagByte5;\r
100     __u8  ecc1[3];\r
101     __u8  tagByte6;\r
102     __u8  tagByte7;\r
103     __u8  ecc2[3];\r
104 } yaffs_Spare;\r
105 \r
106 // Block data in RAM\r
107 \r
108 typedef enum {\r
109         YAFFS_BLOCK_STATE_UddNKNOWN     = 0,\r
110         YAFFS_BLOCK_STATE_SCANNING,             // Used while the block is being scanned.\r
111                                                                         // NB Don't erase blocks while they're being scanned\r
112         \r
113         YAFFS_BLOCK_STATE_EMPTY,                // This block is empty\r
114         \r
115         YAFFS_BLOCK_STATE_ALLOCATING,   // This block is partially allocated. \r
116                                                                         // This is the one currently being used for page\r
117                                                                         // allocation. Should never be more than one of these\r
118                                                         \r
119 \r
120         YAFFS_BLOCK_STATE_FULL,                 // All the pages in this block have been allocated.\r
121                                                                         // At least one page holds valid data.\r
122                                                          \r
123         YAFFS_BLOCK_STATE_DIRTY,                // All pages have been allocated and deleted. \r
124                                                                         // Erase me, reuse me.\r
125                                                         \r
126         YAFFS_BLOCK_STATE_DEAD = 0x77   // This block has failed and is not in use\r
127 \r
128 } yaffs_BlockState;\r
129 \r
130 \r
131 \r
132 \r
133 typedef struct\r
134 {\r
135         __u32 pageBits;   // bitmap of pages in use\r
136     __u8  blockState; // One of the above block states\r
137     __u8  pagesInUse; // number of pages in use\r
138     __u8  needsRetiring:1;      // Data has failed on this block, need to get valid data off\r
139                                                 // and retire the block.\r
140 } yaffs_BlockInfo;\r
141 \r
142 \r
143 //////////////////// Object structure ///////////////////////////\r
144 // This is the object structure as stored on NAND\r
145 \r
146 typedef enum\r
147 {\r
148         YAFFS_OBJECT_TYPE_UNKNOWN,\r
149         YAFFS_OBJECT_TYPE_FILE,\r
150         YAFFS_OBJECT_TYPE_SYMLINK,\r
151         YAFFS_OBJECT_TYPE_DIRECTORY,\r
152         YAFFS_OBJECT_TYPE_HARDLINK,\r
153         YAFFS_OBJECT_TYPE_SPECIAL\r
154 } yaffs_ObjectType;\r
155 \r
156 typedef struct\r
157 {\r
158         yaffs_ObjectType type;\r
159 \r
160         // Apply to everything  \r
161         int   parentObjectId;\r
162         __u16 sum;      // checksum of name\r
163         char  name[YAFFS_MAX_NAME_LENGTH + 1];\r
164 \r
165         // Thes following apply to directories, files, symlinks - not hard links\r
166         __u32 st_mode;  // protection\r
167         __u32 st_uid;   // user ID of owner\r
168         __u32 st_gid;    // group ID of owner \r
169         __u32 st_atime; // time of last access\r
170         __u32 st_mtime; // time of last modification\r
171         __u32 st_ctime; // time of last change\r
172         \r
173         // File size  applies to files only\r
174         int fileSize; \r
175                 \r
176         // Equivalent object id applies to hard links only.\r
177         int  equivalentObjectId;\r
178         \r
179         // Alias is for symlinks only.\r
180         char alias[YAFFS_MAX_ALIAS_LENGTH + 1];\r
181         \r
182         __u32 st_rdev;  // device stuff for block and char devices (maj/min)\r
183         // Roowm to grow...\r
184         __u32 roomToGrow[12];\r
185         \r
186 } yaffs_ObjectHeader;\r
187 \r
188 \r
189 \r
190 ////////////////////  Tnode ///////////////////////////\r
191 \r
192 union yaffs_Tnode_union\r
193 {\r
194         union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];\r
195         __u16 level0[YAFFS_NTNODES_LEVEL0];\r
196         \r
197 };\r
198 \r
199 typedef union yaffs_Tnode_union yaffs_Tnode;\r
200 \r
201 struct yaffs_TnodeList_struct\r
202 {\r
203         struct yaffs_TnodeList_struct *next;\r
204         yaffs_Tnode *tnodes;\r
205 };\r
206 \r
207 typedef struct yaffs_TnodeList_struct yaffs_TnodeList;\r
208 \r
209 \r
210 \r
211 ///////////////////  Object ////////////////////////////////\r
212 // An object can be one of:\r
213 // - a directory (no data, has children links\r
214 // - a regular file (data.... not prunes :->).\r
215 // - a symlink [symbolic link] (the alias).\r
216 // - a hard link\r
217 \r
218 \r
219 typedef struct \r
220 {\r
221         __u32 fileSize;\r
222         __u32 scannedFileSize;\r
223         __u32 topLevel;\r
224         yaffs_Tnode *top;\r
225 } yaffs_FileStructure;\r
226 \r
227 typedef struct\r
228 {\r
229         struct list_head children; // list of child links\r
230 } yaffs_DirectoryStructure;\r
231 \r
232 typedef struct\r
233 {\r
234         char *alias;\r
235 } yaffs_SymLinkStructure;\r
236 \r
237 typedef struct\r
238 {\r
239         struct yaffs_ObjectStruct *equivalentObject;\r
240         __u32   equivalentObjectId;\r
241 } yaffs_HardLinkStructure;\r
242 \r
243 typedef union\r
244 {\r
245         yaffs_FileStructure fileVariant;\r
246         yaffs_DirectoryStructure directoryVariant;\r
247         yaffs_SymLinkStructure symLinkVariant;\r
248         yaffs_HardLinkStructure hardLinkVariant;\r
249 } yaffs_ObjectVariant;\r
250 \r
251 \r
252 struct  yaffs_ObjectStruct\r
253 {\r
254         __u8 fake:1;                    // A fake object has no presence on NAND.\r
255         __u8 renameAllowed:1;\r
256         __u8 unlinkAllowed:1;\r
257         __u8 dirty:1;                   // the object needs to be written to flash\r
258         __u8 valid:1;                   // When the file system is being loaded up, this \r
259                                                         // object might be created before the data\r
260                                                         // is available (ie. file data records appear before the header).\r
261         __u8 serial;                    // serial number of chunk in NAND. Store here so we don't have to\r
262                                                         // read back the old one to update.\r
263         __u16 sum;                              // sum of the name to speed searching\r
264         \r
265         struct yaffs_DeviceStruct *myDev; // The device I'm on\r
266         \r
267                                                                 \r
268         struct list_head hashLink;      // list of objects in this hash bucket\r
269                                                         \r
270 \r
271         struct list_head hardLinks; // all the equivalent hard linked objects\r
272                                                                 // live on this list\r
273         // directory structure stuff\r
274         struct yaffs_ObjectStruct  *parent;     //my parent directory\r
275         struct list_head siblings;      // siblings in a directory\r
276                                                                 // also used for linking up the free list\r
277                 \r
278         // Where's my data in NAND?\r
279         int chunkId;            // where it lives\r
280 \r
281         int nDataChunks;        // really only for debugging.\r
282         \r
283         __u32 objectId;         // the object id value\r
284         \r
285         \r
286         __u32 st_mode;          // protection\r
287         __u32 st_uid;           // user ID of owner\r
288         __u32 st_gid;           // group ID of owner \r
289         __u32 st_atime;         // time of last access\r
290         __u32 st_mtime;         // time of last modification\r
291         __u32 st_ctime;         // time of last change\r
292         __u32 st_rdev;      // device stuff for block and char devices\r
293 \r
294 #ifdef WIN32\r
295         __u32 inUse;\r
296 #endif\r
297 \r
298         \r
299         yaffs_ObjectType variantType;\r
300         \r
301         yaffs_ObjectVariant variant;\r
302         \r
303 };\r
304 \r
305 \r
306 \r
307 typedef struct yaffs_ObjectStruct yaffs_Object;\r
308 \r
309 \r
310 struct yaffs_ObjectList_struct\r
311 {\r
312         yaffs_Object *objects;\r
313         struct yaffs_ObjectList_struct *next;\r
314 };\r
315 \r
316 typedef struct yaffs_ObjectList_struct yaffs_ObjectList;\r
317 \r
318 typedef struct\r
319 {\r
320         struct list_head list;\r
321         __u32 count;\r
322 } yaffs_ObjectBucket;\r
323 \r
324 \r
325 //////////////////// Device ////////////////////////////////\r
326 \r
327 struct yaffs_DeviceStruct\r
328 {\r
329         // Entry parameters set up way early. Yaffs sets up the rest.\r
330         __u32 nBlocks;          // Size of whole device in blocks\r
331         __u32 startBlock;       // Start block we're allowed to use\r
332         __u32 endBlock;         // End block we're allowed to use\r
333         __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16\r
334         __u16 chunkGroupSize; // == 2^^chunkGroupBits\r
335         \r
336         \r
337         void *genericDevice; // Pointer to device context\r
338                                                  // On an mtd this holds the mtd pointer.\r
339         \r
340 #ifdef __KERNEL__\r
341 \r
342         struct semaphore sem;// Semaphore for waiting on erasure.\r
343 \r
344 #endif\r
345         \r
346         \r
347         // NAND access functions (Must be set before calling YAFFS)\r
348         \r
349         int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare);\r
350         int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);\r
351         int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND);        \r
352         int (*initialiseNAND)(struct yaffs_DeviceStruct *dev);\r
353 \r
354 #ifdef __KERNEL__\r
355         void (*putSuperFunc)(struct super_block *sb);\r
356 #endif\r
357 \r
358         // Runtime parameters.\r
359         yaffs_BlockInfo *blockInfo;\r
360         int   nErasedBlocks;\r
361         int   allocationBlock;\r
362         __u32 allocationPage;\r
363         \r
364         // Runtime state\r
365         int   nTnodesCreated;   \r
366         yaffs_Tnode *freeTnodes;\r
367         int  nFreeTnodes;\r
368         yaffs_TnodeList *allocatedTnodeList;\r
369 \r
370 \r
371         int   nObjectsCreated;\r
372         yaffs_Object *freeObjects;\r
373         int   nFreeObjects;\r
374 \r
375         yaffs_ObjectList *allocatedObjectList;\r
376 \r
377         yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];\r
378 \r
379         int       nFreeChunks;\r
380                 \r
381         int   currentDirtyChecker;      // Used to find current dirtiest block\r
382         \r
383         int   garbageCollectionRequired;\r
384         \r
385         // Operations since mount\r
386         int nPageWrites;\r
387         int nPageReads;\r
388         int nBlockErasures;\r
389         int nGCCopies;\r
390         int nRetriedWrites;\r
391         int nRetiredBlocks;\r
392         \r
393         yaffs_Object *rootDir;\r
394         yaffs_Object *lostNFoundDir;\r
395         \r
396         // Buffer areas for storing data to recover from write failures\r
397         __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];\r
398         yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];\r
399         int bufferedBlock;      // Which block is buffered here?\r
400         int doingBufferedBlockRewrite;\r
401         \r
402         int blockSelectedForGC;\r
403         \r
404         \r
405 };\r
406 \r
407 typedef struct yaffs_DeviceStruct yaffs_Device;\r
408 \r
409 \r
410 \r
411 //////////// YAFFS Functions //////////////////\r
412 \r
413 int yaffs_GutsInitialise(yaffs_Device *dev);\r
414 void yaffs_Deinitialise(yaffs_Device *dev);\r
415 \r
416 int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev);\r
417 \r
418 \r
419 // Rename\r
420 int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName);\r
421 \r
422 // generic Object functions\r
423 int yaffs_Unlink(yaffs_Object *dir, const char *name);\r
424 \r
425 // Object access functions.\r
426 int yaffs_GetObjectName(yaffs_Object *obj,char *name,int buffSize);\r
427 int yaffs_GetObjectFileLength(yaffs_Object *obj);\r
428 int yaffs_GetObjectInode(yaffs_Object *obj);\r
429 unsigned yaffs_GetObjectType(yaffs_Object *obj);\r
430 int yaffs_GetObjectLinkCount(yaffs_Object *obj);\r
431 \r
432 // Change inode attributes\r
433 int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr);\r
434 int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr);\r
435 \r
436 // File operations\r
437 int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, __u32 offset, int nBytes);\r
438 int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, int nBytes);\r
439 int yaffs_ResizeFile(yaffs_Object *obj, int newSize);\r
440 \r
441 yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid);\r
442 int yaffs_FlushFile(yaffs_Object *obj);\r
443 \r
444 \r
445 // Directory operations\r
446 yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid);\r
447 yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir,const char *name);\r
448 int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *));\r
449 \r
450 yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,int number);\r
451 \r
452 // Link operations\r
453 yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject);\r
454 \r
455 yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);\r
456 \r
457 // Symlink operations\r
458 yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const char *name, __u32 mode,  __u32 uid, __u32 gid, const char *alias);\r
459 char *yaffs_GetSymlinkAlias(yaffs_Object *obj);\r
460 \r
461 // Special inodes (fifos, sockets and devices)\r
462 yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,__u32 rdev);\r
463 \r
464 \r
465 // Special directories\r
466 yaffs_Object *yaffs_Root(yaffs_Device *dev);\r
467 yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);\r
468 \r
469 \r
470 // Debug dump \r
471 int yaffs_DumpObject(yaffs_Object *obj);\r
472 \r
473 \r
474 void yaffs_GutsTest(yaffs_Device *dev);\r
475 \r
476 \r
477 #endif\r