d37ac44be92775873a5f96a492ff6a8486052dee
[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 = 0x99   // 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 } yaffs_BlockInfo;\r
139 \r
140 \r
141 //////////////////// Object structure ///////////////////////////\r
142 // This is the object structure as stored on NAND\r
143 \r
144 typedef enum\r
145 {\r
146         YAFFS_OBJECT_TYPE_UNKNOWN,\r
147         YAFFS_OBJECT_TYPE_FILE,\r
148         YAFFS_OBJECT_TYPE_SYMLINK,\r
149         YAFFS_OBJECT_TYPE_DIRECTORY,\r
150         YAFFS_OBJECT_TYPE_HARDLINK,\r
151         YAFFS_OBJECT_TYPE_SPECIAL\r
152 } yaffs_ObjectType;\r
153 \r
154 typedef struct\r
155 {\r
156         yaffs_ObjectType type;\r
157 \r
158         // Apply to everything  \r
159         int   parentObjectId;\r
160         __u16 sum;      // checksum of name\r
161         char  name[YAFFS_MAX_NAME_LENGTH + 1];\r
162 \r
163         // Thes following apply to directories, files, symlinks - not hard links\r
164         __u32 st_mode;  // protection\r
165         __u32 st_uid;   // user ID of owner\r
166         __u32 st_gid;    // group ID of owner \r
167         __u32 st_atime; // time of last access\r
168         __u32 st_mtime; // time of last modification\r
169         __u32 st_ctime; // time of last change\r
170         \r
171         // File size  applies to files only\r
172         int fileSize; \r
173                 \r
174         // Equivalent object id applies to hard links only.\r
175         int  equivalentObjectId;\r
176         \r
177         // Alias is for symlinks only.\r
178         char alias[YAFFS_MAX_ALIAS_LENGTH + 1];\r
179         \r
180         __u32 st_rdev;  // device stuff for block and char devices (maj/min)\r
181         // Roowm to grow...\r
182         __u32 roomToGrow[12];\r
183         \r
184 } yaffs_ObjectHeader;\r
185 \r
186 \r
187 \r
188 ////////////////////  Tnode ///////////////////////////\r
189 \r
190 union yaffs_Tnode_union\r
191 {\r
192         union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];\r
193         __u16 level0[YAFFS_NTNODES_LEVEL0];\r
194         \r
195 };\r
196 \r
197 typedef union yaffs_Tnode_union yaffs_Tnode;\r
198 \r
199 struct yaffs_TnodeList_struct\r
200 {\r
201         struct yaffs_TnodeList_struct *next;\r
202         yaffs_Tnode *tnodes;\r
203 };\r
204 \r
205 typedef struct yaffs_TnodeList_struct yaffs_TnodeList;\r
206 \r
207 \r
208 \r
209 ///////////////////  Object ////////////////////////////////\r
210 // An object can be one of:\r
211 // - a directory (no data, has children links\r
212 // - a regular file (data.... not prunes :->).\r
213 // - a symlink [symbolic link] (the alias).\r
214 // - a hard link\r
215 \r
216 \r
217 typedef struct \r
218 {\r
219         __u32 fileSize;\r
220         __u32 scannedFileSize;\r
221         __u32 topLevel;\r
222         yaffs_Tnode *top;\r
223 } yaffs_FileStructure;\r
224 \r
225 typedef struct\r
226 {\r
227         struct list_head children; // list of child links\r
228 } yaffs_DirectoryStructure;\r
229 \r
230 typedef struct\r
231 {\r
232         char *alias;\r
233 } yaffs_SymLinkStructure;\r
234 \r
235 typedef struct\r
236 {\r
237         struct yaffs_ObjectStruct *equivalentObject;\r
238         __u32   equivalentObjectId;\r
239 } yaffs_HardLinkStructure;\r
240 \r
241 typedef union\r
242 {\r
243         yaffs_FileStructure fileVariant;\r
244         yaffs_DirectoryStructure directoryVariant;\r
245         yaffs_SymLinkStructure symLinkVariant;\r
246         yaffs_HardLinkStructure hardLinkVariant;\r
247 } yaffs_ObjectVariant;\r
248 \r
249 \r
250 struct  yaffs_ObjectStruct\r
251 {\r
252         __u8 fake:1;                    // A fake object has no presence on NAND.\r
253         __u8 renameAllowed:1;\r
254         __u8 unlinkAllowed:1;\r
255         __u8 dirty:1;                   // the object needs to be written to flash\r
256         __u8 valid:1;                   // When the file system is being loaded up, this \r
257                                                         // object might be created before the data\r
258                                                         // is available (ie. file data records appear before the header).\r
259         __u8 serial;                    // serial number of chunk in NAND. Store here so we don't have to\r
260                                                         // read back the old one to update.\r
261         __u16 sum;                              // sum of the name to speed searching\r
262         \r
263         struct yaffs_DeviceStruct *myDev; // The device I'm on\r
264         \r
265                                                                 \r
266         struct list_head hashLink;      // list of objects in this hash bucket\r
267                                                         \r
268 \r
269         struct list_head hardLinks; // all the equivalent hard linked objects\r
270                                                                 // live on this list\r
271         // directory structure stuff\r
272         struct yaffs_ObjectStruct  *parent;     //my parent directory\r
273         struct list_head siblings;      // siblings in a directory\r
274                                                                 // also used for linking up the free list\r
275                 \r
276         // Where's my data in NAND?\r
277         int chunkId;            // where it lives\r
278 \r
279         int nDataChunks;        // really only for debugging.\r
280         \r
281         __u32 objectId;         // the object id value\r
282         \r
283         \r
284         __u32 st_mode;          // protection\r
285         __u32 st_uid;           // user ID of owner\r
286         __u32 st_gid;           // group ID of owner \r
287         __u32 st_atime;         // time of last access\r
288         __u32 st_mtime;         // time of last modification\r
289         __u32 st_ctime;         // time of last change\r
290         __u32 st_rdev;      // device stuff for block and char devices\r
291 \r
292 #ifdef WIN32\r
293         __u32 inUse;\r
294 #endif\r
295 \r
296         \r
297         yaffs_ObjectType variantType;\r
298         \r
299         yaffs_ObjectVariant variant;\r
300         \r
301 };\r
302 \r
303 \r
304 \r
305 typedef struct yaffs_ObjectStruct yaffs_Object;\r
306 \r
307 \r
308 struct yaffs_ObjectList_struct\r
309 {\r
310         yaffs_Object *objects;\r
311         struct yaffs_ObjectList_struct *next;\r
312 };\r
313 \r
314 typedef struct yaffs_ObjectList_struct yaffs_ObjectList;\r
315 \r
316 typedef struct\r
317 {\r
318         struct list_head list;\r
319         __u32 count;\r
320 } yaffs_ObjectBucket;\r
321 \r
322 \r
323 //////////////////// Device ////////////////////////////////\r
324 \r
325 struct yaffs_DeviceStruct\r
326 {\r
327         // Entry parameters set up way early. Yaffs sets up the rest.\r
328         __u32 nBlocks;          // Size of whole device in blocks\r
329         __u32 startBlock;       // Start block we're allowed to use\r
330         __u32 endBlock;         // End block we're allowed to use\r
331         __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16\r
332         __u16 chunkGroupSize; // == 2^^chunkGroupBits\r
333         \r
334         \r
335         void *genericDevice; // Pointer to device context\r
336                                                  // On an mtd this holds the mtd pointer.\r
337         \r
338 #ifdef __KERNEL__\r
339 \r
340         struct semaphore sem;// Semaphore for waiting on erasure.\r
341 \r
342 #endif\r
343         \r
344         \r
345         // NAND access functions (Must be set before calling YAFFS)\r
346         \r
347         int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare);\r
348         int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);\r
349         int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND);        \r
350         int (*initialiseNAND)(struct yaffs_DeviceStruct *dev);\r
351 \r
352 #ifdef __KERNEL__\r
353         void (*putSuperFunc)(struct super_block *sb);\r
354 #endif\r
355 \r
356         // Runtime parameters.\r
357         yaffs_BlockInfo *blockInfo;\r
358         int   nErasedBlocks;\r
359         int   allocationBlock;\r
360         __u32 allocationPage;\r
361         \r
362         // Runtime state\r
363         int   nTnodesCreated;   \r
364         yaffs_Tnode *freeTnodes;\r
365         int  nFreeTnodes;\r
366         yaffs_TnodeList *allocatedTnodeList;\r
367 \r
368 \r
369         int   nObjectsCreated;\r
370         yaffs_Object *freeObjects;\r
371         int   nFreeObjects;\r
372 \r
373         yaffs_ObjectList *allocatedObjectList;\r
374 \r
375         yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];\r
376 \r
377         int       nFreeChunks;\r
378                 \r
379         int   currentDirtyChecker;      // Used to find current dirtiest block\r
380         \r
381         int   garbageCollectionRequired;\r
382         \r
383         // Operations since mount\r
384         int nPageWrites;\r
385         int nPageReads;\r
386         int nBlockErasures;\r
387         int nGCCopies;\r
388         int nRetriedWrites;\r
389         \r
390         yaffs_Object *rootDir;\r
391         yaffs_Object *lostNFoundDir;\r
392         \r
393         \r
394 };\r
395 \r
396  typedef struct yaffs_DeviceStruct yaffs_Device;\r
397 \r
398 \r
399 \r
400 //////////// YAFFS Functions //////////////////\r
401 \r
402 int yaffs_GutsInitialise(yaffs_Device *dev);\r
403 void yaffs_Deinitialise(yaffs_Device *dev);\r
404 \r
405 int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev);\r
406 \r
407 \r
408 // Rename\r
409 int yaffs_RenameObject(yaffs_Object *oldDir, const char *oldName, yaffs_Object *newDir, const char *newName);\r
410 \r
411 // generic Object functions\r
412 int yaffs_Unlink(yaffs_Object *dir, const char *name);\r
413 \r
414 // Object access functions.\r
415 int yaffs_GetObjectName(yaffs_Object *obj,char *name,int buffSize);\r
416 int yaffs_GetObjectFileLength(yaffs_Object *obj);\r
417 int yaffs_GetObjectInode(yaffs_Object *obj);\r
418 unsigned yaffs_GetObjectType(yaffs_Object *obj);\r
419 int yaffs_GetObjectLinkCount(yaffs_Object *obj);\r
420 \r
421 // Change inode attributes\r
422 int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr);\r
423 int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr);\r
424 \r
425 // File operations\r
426 int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, __u32 offset, int nBytes);\r
427 int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, int nBytes);\r
428 int yaffs_ResizeFile(yaffs_Object *obj, int newSize);\r
429 \r
430 yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid);\r
431 int yaffs_FlushFile(yaffs_Object *obj);\r
432 \r
433 \r
434 // Directory operations\r
435 yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid);\r
436 yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir,const char *name);\r
437 int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *));\r
438 \r
439 yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,int number);\r
440 \r
441 // Link operations\r
442 yaffs_Object *yaffs_Link(yaffs_Object *parent, const char *name, yaffs_Object *equivalentObject);\r
443 \r
444 yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);\r
445 \r
446 // Symlink operations\r
447 yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const char *name, __u32 mode,  __u32 uid, __u32 gid, const char *alias);\r
448 char *yaffs_GetSymlinkAlias(yaffs_Object *obj);\r
449 \r
450 // Special inodes (fifos, sockets and devices)\r
451 yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const char *name, __u32 mode, __u32 uid, __u32 gid,__u32 rdev);\r
452 \r
453 \r
454 // Special directories\r
455 yaffs_Object *yaffs_Root(yaffs_Device *dev);\r
456 yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);\r
457 \r
458 \r
459 // Debug dump \r
460 int yaffs_DumpObject(yaffs_Object *obj);\r
461 \r
462 \r
463 void yaffs_GutsTest(yaffs_Device *dev);\r
464 \r
465 \r
466 #endif\r