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