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