[kernel] generic-2.6/2.6.28: sync yaffs code with the current CVS version
[openwrt/svn-archive/archive.git] / target / linux / generic-2.6 / patches-2.6.28 / 511-yaffs-cvs-2009-01-23.patch
1 --- a/fs/yaffs2/yaffs_tagscompat.h
2 +++ b/fs/yaffs2/yaffs_tagscompat.h
3 @@ -30,8 +30,9 @@ int yaffs_TagsCompatabilityReadChunkWith
4 int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
5 int blockNo);
6 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
7 - int blockNo, yaffs_BlockState *
8 - state, int *sequenceNumber);
9 + int blockNo,
10 + yaffs_BlockState *state,
11 + __u32 *sequenceNumber);
12
13 void yaffs_CalcTagsECC(yaffs_Tags * tags);
14 int yaffs_CheckECCOnTags(yaffs_Tags * tags);
15 --- a/fs/yaffs2/Kconfig
16 +++ b/fs/yaffs2/Kconfig
17 @@ -43,7 +43,8 @@ config YAFFS_9BYTE_TAGS
18 format that you need to continue to support. New data written
19 also uses the older-style format. Note: Use of this option
20 generally requires that MTD's oob layout be adjusted to use the
21 - older-style format. See notes on tags formats and MTD versions.
22 + older-style format. See notes on tags formats and MTD versions
23 + in yaffs_mtdif1.c.
24
25 If unsure, say N.
26
27 @@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD
28
29 If unsure, say N.
30
31 -config YAFFS_CHECKPOINT_RESERVED_BLOCKS
32 - int "Reserved blocks for checkpointing"
33 - depends on YAFFS_YAFFS2
34 - default 10
35 - help
36 - Give the number of Blocks to reserve for checkpointing.
37 - Checkpointing saves the state at unmount so that mounting is
38 - much faster as a scan of all the flash to regenerate this state
39 - is not needed. These Blocks are reserved per partition, so if
40 - you have very small partitions the default (10) may be a mess
41 - for you. You can set this value to 0, but that does not mean
42 - checkpointing is disabled at all. There only won't be any
43 - specially reserved blocks for checkpointing, so if there is
44 - enough free space on the filesystem, it will be used for
45 - checkpointing.
46 -
47 - If unsure, leave at default (10), but don't wonder if there are
48 - always 2MB used on your large page device partition (10 x 2k
49 - pagesize). When using small partitions or when being very small
50 - on space, you probably want to set this to zero.
51
52 config YAFFS_DISABLE_WIDE_TNODES
53 bool "Turn off wide tnodes"
54 --- a/fs/yaffs2/yaffs_mtdif.h
55 +++ b/fs/yaffs2/yaffs_mtdif.h
56 @@ -18,6 +18,11 @@
57
58 #include "yaffs_guts.h"
59
60 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
61 +extern struct nand_oobinfo yaffs_oobinfo;
62 +extern struct nand_oobinfo yaffs_noeccinfo;
63 +#endif
64 +
65 int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
66 const __u8 * data, const yaffs_Spare * spare);
67 int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
68 --- a/fs/yaffs2/devextras.h
69 +++ b/fs/yaffs2/devextras.h
70 @@ -1,5 +1,5 @@
71 /*
72 - * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
73 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
74 *
75 * Copyright (C) 2002-2007 Aleph One Ltd.
76 * for Toby Churchill Ltd and Brightstar Engineering
77 @@ -14,203 +14,145 @@
78 */
79
80 /*
81 - * This file is just holds extra declarations used during development.
82 - * Most of these are from kernel includes placed here so we can use them in
83 - * applications.
84 + * This file is just holds extra declarations of macros that would normally
85 + * be providesd in the Linux kernel. These macros have been written from
86 + * scratch but are functionally equivalent to the Linux ones.
87 *
88 */
89
90 #ifndef __EXTRAS_H__
91 #define __EXTRAS_H__
92
93 -#if defined WIN32
94 -#define __inline__ __inline
95 -#define new newHack
96 -#endif
97 -
98 -#if !(defined __KERNEL__) || (defined WIN32)
99
100 -/* User space defines */
101 +#if !(defined __KERNEL__)
102
103 +/* Definition of types */
104 typedef unsigned char __u8;
105 typedef unsigned short __u16;
106 typedef unsigned __u32;
107
108 +#endif
109 +
110 /*
111 - * Simple doubly linked list implementation.
112 - *
113 - * Some of the internal functions ("__xxx") are useful when
114 - * manipulating whole lists rather than single entries, as
115 - * sometimes we already know the next/prev entries and we can
116 - * generate better code by using them directly rather than
117 - * using the generic single-entry routines.
118 + * This is a simple doubly linked list implementation that matches the
119 + * way the Linux kernel doubly linked list implementation works.
120 */
121
122 -#define prefetch(x) 1
123 -
124 -struct list_head {
125 - struct list_head *next, *prev;
126 +struct ylist_head {
127 + struct ylist_head *next; /* next in chain */
128 + struct ylist_head *prev; /* previous in chain */
129 };
130
131 -#define LIST_HEAD_INIT(name) { &(name), &(name) }
132
133 -#define LIST_HEAD(name) \
134 - struct list_head name = LIST_HEAD_INIT(name)
135 +/* Initialise a static list */
136 +#define YLIST_HEAD(name) \
137 +struct ylist_head name = { &(name),&(name)}
138
139 -#define INIT_LIST_HEAD(ptr) do { \
140 - (ptr)->next = (ptr); (ptr)->prev = (ptr); \
141 -} while (0)
142
143 -/*
144 - * Insert a new entry between two known consecutive entries.
145 - *
146 - * This is only for internal list manipulation where we know
147 - * the prev/next entries already!
148 - */
149 -static __inline__ void __list_add(struct list_head *new,
150 - struct list_head *prev,
151 - struct list_head *next)
152 -{
153 - next->prev = new;
154 - new->next = next;
155 - new->prev = prev;
156 - prev->next = new;
157 -}
158
159 -/**
160 - * list_add - add a new entry
161 - * @new: new entry to be added
162 - * @head: list head to add it after
163 - *
164 - * Insert a new entry after the specified head.
165 - * This is good for implementing stacks.
166 - */
167 -static __inline__ void list_add(struct list_head *new, struct list_head *head)
168 -{
169 - __list_add(new, head, head->next);
170 -}
171 +/* Initialise a list head to an empty list */
172 +#define YINIT_LIST_HEAD(p) \
173 +do { \
174 + (p)->next = (p);\
175 + (p)->prev = (p); \
176 +} while(0)
177
178 -/**
179 - * list_add_tail - add a new entry
180 - * @new: new entry to be added
181 - * @head: list head to add it before
182 - *
183 - * Insert a new entry before the specified head.
184 - * This is useful for implementing queues.
185 - */
186 -static __inline__ void list_add_tail(struct list_head *new,
187 - struct list_head *head)
188 +
189 +/* Add an element to a list */
190 +static __inline__ void ylist_add(struct ylist_head *newEntry,
191 + struct ylist_head *list)
192 {
193 - __list_add(new, head->prev, head);
194 + struct ylist_head *listNext = list->next;
195 +
196 + list->next = newEntry;
197 + newEntry->prev = list;
198 + newEntry->next = listNext;
199 + listNext->prev = newEntry;
200 +
201 }
202
203 -/*
204 - * Delete a list entry by making the prev/next entries
205 - * point to each other.
206 - *
207 - * This is only for internal list manipulation where we know
208 - * the prev/next entries already!
209 - */
210 -static __inline__ void __list_del(struct list_head *prev,
211 - struct list_head *next)
212 +static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
213 + struct ylist_head *list)
214 {
215 - next->prev = prev;
216 - prev->next = next;
217 + struct ylist_head *listPrev = list->prev;
218 +
219 + list->prev = newEntry;
220 + newEntry->next = list;
221 + newEntry->prev = listPrev;
222 + listPrev->next = newEntry;
223 +
224 }
225
226 -/**
227 - * list_del - deletes entry from list.
228 - * @entry: the element to delete from the list.
229 - * Note: list_empty on entry does not return true after this, the entry is
230 - * in an undefined state.
231 - */
232 -static __inline__ void list_del(struct list_head *entry)
233 +
234 +/* Take an element out of its current list, with or without
235 + * reinitialising the links.of the entry*/
236 +static __inline__ void ylist_del(struct ylist_head *entry)
237 {
238 - __list_del(entry->prev, entry->next);
239 + struct ylist_head *listNext = entry->next;
240 + struct ylist_head *listPrev = entry->prev;
241 +
242 + listNext->prev = listPrev;
243 + listPrev->next = listNext;
244 +
245 }
246
247 -/**
248 - * list_del_init - deletes entry from list and reinitialize it.
249 - * @entry: the element to delete from the list.
250 - */
251 -static __inline__ void list_del_init(struct list_head *entry)
252 +static __inline__ void ylist_del_init(struct ylist_head *entry)
253 {
254 - __list_del(entry->prev, entry->next);
255 - INIT_LIST_HEAD(entry);
256 + ylist_del(entry);
257 + entry->next = entry->prev = entry;
258 }
259
260 -/**
261 - * list_empty - tests whether a list is empty
262 - * @head: the list to test.
263 - */
264 -static __inline__ int list_empty(struct list_head *head)
265 +
266 +/* Test if the list is empty */
267 +static __inline__ int ylist_empty(struct ylist_head *entry)
268 {
269 - return head->next == head;
270 + return (entry->next == entry);
271 }
272
273 -/**
274 - * list_splice - join two lists
275 - * @list: the new list to add.
276 - * @head: the place to add it in the first list.
277 +
278 +/* ylist_entry takes a pointer to a list entry and offsets it to that
279 + * we can find a pointer to the object it is embedded in.
280 */
281 -static __inline__ void list_splice(struct list_head *list,
282 - struct list_head *head)
283 -{
284 - struct list_head *first = list->next;
285 +
286 +
287 +#define ylist_entry(entry, type, member) \
288 + ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
289
290 - if (first != list) {
291 - struct list_head *last = list->prev;
292 - struct list_head *at = head->next;
293 -
294 - first->prev = head;
295 - head->next = first;
296 -
297 - last->next = at;
298 - at->prev = last;
299 - }
300 -}
301
302 -/**
303 - * list_entry - get the struct for this entry
304 - * @ptr: the &struct list_head pointer.
305 - * @type: the type of the struct this is embedded in.
306 - * @member: the name of the list_struct within the struct.
307 +/* ylist_for_each and list_for_each_safe iterate over lists.
308 + * ylist_for_each_safe uses temporary storage to make the list delete safe
309 */
310 -#define list_entry(ptr, type, member) \
311 - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
312
313 -/**
314 - * list_for_each - iterate over a list
315 - * @pos: the &struct list_head to use as a loop counter.
316 - * @head: the head for your list.
317 - */
318 -#define list_for_each(pos, head) \
319 - for (pos = (head)->next, prefetch(pos->next); pos != (head); \
320 - pos = pos->next, prefetch(pos->next))
321 -
322 -/**
323 - * list_for_each_safe - iterate over a list safe against removal
324 - * of list entry
325 - * @pos: the &struct list_head to use as a loop counter.
326 - * @n: another &struct list_head to use as temporary storage
327 - * @head: the head for your list.
328 - */
329 -#define list_for_each_safe(pos, n, head) \
330 - for (pos = (head)->next, n = pos->next; pos != (head); \
331 - pos = n, n = pos->next)
332 +#define ylist_for_each(itervar, list) \
333 + for (itervar = (list)->next; itervar != (list); itervar = itervar->next )
334
335 -/*
336 - * File types
337 - */
338 -#define DT_UNKNOWN 0
339 -#define DT_FIFO 1
340 -#define DT_CHR 2
341 +#define ylist_for_each_safe(itervar,saveVar, list) \
342 + for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \
343 + itervar = saveVar, saveVar = saveVar->next)
344 +
345 +
346 +#if !(defined __KERNEL__)
347 +
348 +
349 +#ifndef WIN32
350 +#include <sys/stat.h>
351 +#endif
352 +
353 +
354 +#ifdef CONFIG_YAFFS_PROVIDE_DEFS
355 +/* File types */
356 +
357 +
358 +#define DT_UNKNOWN 0
359 +#define DT_FIFO 1
360 +#define DT_CHR 2
361 #define DT_DIR 4
362 #define DT_BLK 6
363 -#define DT_REG 8
364 -#define DT_LNK 10
365 -#define DT_SOCK 12
366 -#define DT_WHT 14
367 +#define DT_REG 8
368 +#define DT_LNK 10
369 +#define DT_SOCK 12
370 +#define DT_WHT 14
371 +
372
373 #ifndef WIN32
374 #include <sys/stat.h>
375 @@ -220,17 +162,13 @@ static __inline__ void list_splice(struc
376 * Attribute flags. These should be or-ed together to figure out what
377 * has been changed!
378 */
379 -#define ATTR_MODE 1
380 -#define ATTR_UID 2
381 +#define ATTR_MODE 1
382 +#define ATTR_UID 2
383 #define ATTR_GID 4
384 #define ATTR_SIZE 8
385 #define ATTR_ATIME 16
386 #define ATTR_MTIME 32
387 #define ATTR_CTIME 64
388 -#define ATTR_ATIME_SET 128
389 -#define ATTR_MTIME_SET 256
390 -#define ATTR_FORCE 512 /* Not a change, but a change it */
391 -#define ATTR_ATTR_FLAG 1024
392
393 struct iattr {
394 unsigned int ia_valid;
395 @@ -241,24 +179,21 @@ struct iattr {
396 unsigned ia_atime;
397 unsigned ia_mtime;
398 unsigned ia_ctime;
399 - unsigned int ia_attr_flags;
400 + unsigned int ia_attr_flags;
401 };
402
403 +#endif
404 +
405 +
406 #define KERN_DEBUG
407
408 #else
409
410 -#ifndef WIN32
411 #include <linux/types.h>
412 -#include <linux/list.h>
413 #include <linux/fs.h>
414 #include <linux/stat.h>
415 -#endif
416
417 #endif
418
419 -#if defined WIN32
420 -#undef new
421 -#endif
422
423 #endif
424 --- a/fs/yaffs2/yaffs_packedtags2.c
425 +++ b/fs/yaffs2/yaffs_packedtags2.c
426 @@ -37,60 +37,70 @@
427 #define EXTRA_OBJECT_TYPE_SHIFT (28)
428 #define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
429
430 -static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
431 +
432 +static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
433 {
434 T(YAFFS_TRACE_MTD,
435 (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
436 - pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
437 - pt->t.sequenceNumber));
438 + ptt->objectId, ptt->chunkId, ptt->byteCount,
439 + ptt->sequenceNumber));
440 +}
441 +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
442 +{
443 + yaffs_DumpPackedTags2TagsPart(&pt->t);
444 }
445
446 static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
447 {
448 T(YAFFS_TRACE_MTD,
449 (TSTR
450 - ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
451 - "%d del %d ser %d seq %d"
452 + ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
453 TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
454 t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
455 t->sequenceNumber));
456
457 }
458
459 -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
460 +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
461 {
462 - pt->t.chunkId = t->chunkId;
463 - pt->t.sequenceNumber = t->sequenceNumber;
464 - pt->t.byteCount = t->byteCount;
465 - pt->t.objectId = t->objectId;
466 + ptt->chunkId = t->chunkId;
467 + ptt->sequenceNumber = t->sequenceNumber;
468 + ptt->byteCount = t->byteCount;
469 + ptt->objectId = t->objectId;
470
471 if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
472 /* Store the extra header info instead */
473 /* We save the parent object in the chunkId */
474 - pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
475 + ptt->chunkId = EXTRA_HEADER_INFO_FLAG
476 | t->extraParentObjectId;
477 if (t->extraIsShrinkHeader) {
478 - pt->t.chunkId |= EXTRA_SHRINK_FLAG;
479 + ptt->chunkId |= EXTRA_SHRINK_FLAG;
480 }
481 if (t->extraShadows) {
482 - pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
483 + ptt->chunkId |= EXTRA_SHADOWS_FLAG;
484 }
485
486 - pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
487 - pt->t.objectId |=
488 + ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
489 + ptt->objectId |=
490 (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
491
492 if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
493 - pt->t.byteCount = t->extraEquivalentObjectId;
494 + ptt->byteCount = t->extraEquivalentObjectId;
495 } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
496 - pt->t.byteCount = t->extraFileLength;
497 + ptt->byteCount = t->extraFileLength;
498 } else {
499 - pt->t.byteCount = 0;
500 + ptt->byteCount = 0;
501 }
502 }
503
504 - yaffs_DumpPackedTags2(pt);
505 + yaffs_DumpPackedTags2TagsPart(ptt);
506 yaffs_DumpTags2(t);
507 +}
508 +
509 +
510 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
511 +{
512 + yaffs_PackTags2TagsPart(&pt->t,t);
513
514 #ifndef YAFFS_IGNORE_TAGS_ECC
515 {
516 @@ -101,20 +111,63 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
517 #endif
518 }
519
520 -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
521 +
522 +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
523 {
524
525 memset(t, 0, sizeof(yaffs_ExtendedTags));
526
527 yaffs_InitialiseTags(t);
528
529 + if (ptt->sequenceNumber != 0xFFFFFFFF) {
530 + t->blockBad = 0;
531 + t->chunkUsed = 1;
532 + t->objectId = ptt->objectId;
533 + t->chunkId = ptt->chunkId;
534 + t->byteCount = ptt->byteCount;
535 + t->chunkDeleted = 0;
536 + t->serialNumber = 0;
537 + t->sequenceNumber = ptt->sequenceNumber;
538 +
539 + /* Do extra header info stuff */
540 +
541 + if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
542 + t->chunkId = 0;
543 + t->byteCount = 0;
544 +
545 + t->extraHeaderInfoAvailable = 1;
546 + t->extraParentObjectId =
547 + ptt->chunkId & (~(ALL_EXTRA_FLAGS));
548 + t->extraIsShrinkHeader =
549 + (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
550 + t->extraShadows =
551 + (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
552 + t->extraObjectType =
553 + ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
554 + t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
555 +
556 + if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
557 + t->extraEquivalentObjectId = ptt->byteCount;
558 + } else {
559 + t->extraFileLength = ptt->byteCount;
560 + }
561 + }
562 + }
563 +
564 + yaffs_DumpPackedTags2TagsPart(ptt);
565 + yaffs_DumpTags2(t);
566 +
567 +}
568 +
569 +
570 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
571 +{
572 +
573 + yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
574 +
575 if (pt->t.sequenceNumber != 0xFFFFFFFF) {
576 /* Page is in use */
577 -#ifdef YAFFS_IGNORE_TAGS_ECC
578 - {
579 - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
580 - }
581 -#else
582 +#ifndef YAFFS_IGNORE_TAGS_ECC
583 {
584 yaffs_ECCOther ecc;
585 int result;
586 @@ -129,54 +182,27 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
587 &pt->ecc, &ecc);
588 switch(result){
589 case 0:
590 - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
591 + eccResult = YAFFS_ECC_RESULT_NO_ERROR;
592 break;
593 case 1:
594 - t->eccResult = YAFFS_ECC_RESULT_FIXED;
595 + eccResult = YAFFS_ECC_RESULT_FIXED;
596 break;
597 case -1:
598 - t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
599 + eccResult = YAFFS_ECC_RESULT_UNFIXED;
600 break;
601 default:
602 - t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
603 + eccResult = YAFFS_ECC_RESULT_UNKNOWN;
604 }
605 }
606 #endif
607 - t->blockBad = 0;
608 - t->chunkUsed = 1;
609 - t->objectId = pt->t.objectId;
610 - t->chunkId = pt->t.chunkId;
611 - t->byteCount = pt->t.byteCount;
612 - t->chunkDeleted = 0;
613 - t->serialNumber = 0;
614 - t->sequenceNumber = pt->t.sequenceNumber;
615 -
616 - /* Do extra header info stuff */
617 -
618 - if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
619 - t->chunkId = 0;
620 - t->byteCount = 0;
621 -
622 - t->extraHeaderInfoAvailable = 1;
623 - t->extraParentObjectId =
624 - pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
625 - t->extraIsShrinkHeader =
626 - (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
627 - t->extraShadows =
628 - (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
629 - t->extraObjectType =
630 - pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
631 - t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
632 -
633 - if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
634 - t->extraEquivalentObjectId = pt->t.byteCount;
635 - } else {
636 - t->extraFileLength = pt->t.byteCount;
637 - }
638 - }
639 }
640
641 + yaffs_UnpackTags2TagsPart(t,&pt->t);
642 +
643 + t->eccResult = eccResult;
644 +
645 yaffs_DumpPackedTags2(pt);
646 yaffs_DumpTags2(t);
647
648 }
649 +
650 --- a/fs/yaffs2/yaffs_ecc.c
651 +++ b/fs/yaffs2/yaffs_ecc.c
652 @@ -29,7 +29,7 @@
653 */
654
655 const char *yaffs_ecc_c_version =
656 - "$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $";
657 + "$Id: yaffs_ecc.c,v 1.10 2007-12-13 15:35:17 wookey Exp $";
658
659 #include "yportenv.h"
660
661 --- a/fs/yaffs2/yaffs_packedtags2.h
662 +++ b/fs/yaffs2/yaffs_packedtags2.h
663 @@ -33,6 +33,11 @@ typedef struct {
664 yaffs_ECCOther ecc;
665 } yaffs_PackedTags2;
666
667 +/* Full packed tags with ECC, used for oob tags */
668 void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
669 void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
670 +
671 +/* Only the tags part (no ECC for use with inband tags */
672 +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * pt, const yaffs_ExtendedTags * t);
673 +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * pt);
674 #endif
675 --- a/fs/yaffs2/yportenv.h
676 +++ b/fs/yaffs2/yportenv.h
677 @@ -17,6 +17,14 @@
678 #ifndef __YPORTENV_H__
679 #define __YPORTENV_H__
680
681 +/*
682 + * Define the MTD version in terms of Linux Kernel versions
683 + * This allows yaffs to be used independantly of the kernel
684 + * as well as with it.
685 + */
686 +
687 +#define MTD_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
688 +
689 #if defined CONFIG_YAFFS_WINCE
690
691 #include "ywinceenv.h"
692 @@ -26,7 +34,10 @@
693 #include "moduleconfig.h"
694
695 /* Linux kernel */
696 +
697 #include <linux/version.h>
698 +#define MTD_VERSION_CODE LINUX_VERSION_CODE
699 +
700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
701 #include <linux/config.h>
702 #endif
703 @@ -40,6 +51,7 @@
704 #define YCHAR char
705 #define YUCHAR unsigned char
706 #define _Y(x) x
707 +#define yaffs_strcat(a,b) strcat(a,b)
708 #define yaffs_strcpy(a,b) strcpy(a,b)
709 #define yaffs_strncpy(a,b,c) strncpy(a,b,c)
710 #define yaffs_strncmp(a,b,c) strncmp(a,b,c)
711 @@ -90,6 +102,8 @@
712
713 #elif defined CONFIG_YAFFS_DIRECT
714
715 +#define MTD_VERSION_CODE MTD_VERSION(2,6,22)
716 +
717 /* Direct interface */
718 #include "ydirectenv.h"
719
720 @@ -111,6 +125,7 @@
721 #define YCHAR char
722 #define YUCHAR unsigned char
723 #define _Y(x) x
724 +#define yaffs_strcat(a,b) strcat(a,b)
725 #define yaffs_strcpy(a,b) strcpy(a,b)
726 #define yaffs_strncpy(a,b,c) strncpy(a,b,c)
727 #define yaffs_strlen(s) strlen(s)
728 @@ -180,8 +195,8 @@ extern unsigned int yaffs_wr_attempts;
729
730 #define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
731
732 -#ifndef CONFIG_YAFFS_WINCE
733 -#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
734 +#ifndef YBUG
735 +#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0)
736 #endif
737
738 #endif
739 --- a/fs/yaffs2/Makefile
740 +++ b/fs/yaffs2/Makefile
741 @@ -5,7 +5,6 @@
742 obj-$(CONFIG_YAFFS_FS) += yaffs.o
743
744 yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
745 -yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
746 +yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
747 yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
748 -yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o
749 -yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o
750 +yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
751 --- a/fs/yaffs2/yaffs_mtdif1-compat.c
752 +++ /dev/null
753 @@ -1,434 +0,0 @@
754 -From ian@brightstareng.com Fri May 18 15:06:49 2007
755 -From ian@brightstareng.com Fri May 18 15:08:21 2007
756 -Received: from 206.173.66.57.ptr.us.xo.net ([206.173.66.57] helo=zebra.brightstareng.com)
757 - by apollo.linkchoose.co.uk with esmtp (Exim 4.60)
758 - (envelope-from <ian@brightstareng.com>)
759 - id 1Hp380-00011e-T6
760 - for david.goodenough@linkchoose.co.uk; Fri, 18 May 2007 15:08:21 +0100
761 -Received: from localhost (localhost.localdomain [127.0.0.1])
762 - by zebra.brightstareng.com (Postfix) with ESMTP
763 - id 4819F28C004; Fri, 18 May 2007 10:07:49 -0400 (EDT)
764 -Received: from zebra.brightstareng.com ([127.0.0.1])
765 - by localhost (zebra [127.0.0.1]) (amavisd-new, port 10024) with ESMTP
766 - id 05328-06; Fri, 18 May 2007 10:07:16 -0400 (EDT)
767 -Received: from pippin (unknown [192.168.1.25])
768 - by zebra.brightstareng.com (Postfix) with ESMTP
769 - id 8BEF528C1BC; Fri, 18 May 2007 10:06:53 -0400 (EDT)
770 -From: Ian McDonnell <ian@brightstareng.com>
771 -To: David Goodenough <david.goodenough@linkchoose.co.uk>
772 -Subject: Re: something tested this time -- yaffs_mtdif1-compat.c
773 -Date: Fri, 18 May 2007 10:06:49 -0400
774 -User-Agent: KMail/1.9.1
775 -References: <200705142207.06909.ian@brightstareng.com> <200705171131.53536.ian@brightstareng.com> <200705181334.32166.david.goodenough@linkchoose.co.uk>
776 -In-Reply-To: <200705181334.32166.david.goodenough@linkchoose.co.uk>
777 -Cc: Andrea Conti <alyf@alyf.net>,
778 - Charles Manning <manningc2@actrix.gen.nz>
779 -MIME-Version: 1.0
780 -Content-Type: Multipart/Mixed;
781 - boundary="Boundary-00=_5LbTGmt62YoutxM"
782 -Message-Id: <200705181006.49860.ian@brightstareng.com>
783 -X-Virus-Scanned: by amavisd-new at brightstareng.com
784 -Status: R
785 -X-Status: NT
786 -X-KMail-EncryptionState:
787 -X-KMail-SignatureState:
788 -X-KMail-MDN-Sent:
789 -
790 ---Boundary-00=_5LbTGmt62YoutxM
791 -Content-Type: text/plain;
792 - charset="iso-8859-15"
793 -Content-Transfer-Encoding: 7bit
794 -Content-Disposition: inline
795 -
796 -David, Andrea,
797 -
798 -On Friday 18 May 2007 08:34, you wrote:
799 -> Yea team. With this fix in place (I put it in the wrong place
800 -> at first) I can now mount and ls the Yaffs partition without
801 -> an error messages!
802 -
803 -Good news!
804 -
805 -Attached is a newer yaffs_mtdif1.c with a bandaid to help the
806 -2.6.18 and 2.6.19 versions of MTD not trip on the oob read.
807 -See the LINUX_VERSION_CODE conditional in
808 -nandmtd1_ReadChunkWithTagsFromNAND.
809 -
810 --imcd
811 -
812 ---Boundary-00=_5LbTGmt62YoutxM
813 -Content-Type: text/x-csrc;
814 - charset="iso-8859-15";
815 - name="yaffs_mtdif1.c"
816 -Content-Transfer-Encoding: 7bit
817 -Content-Disposition: attachment;
818 - filename="yaffs_mtdif1.c"
819 -
820 -/*
821 - * YAFFS: Yet another FFS. A NAND-flash specific file system.
822 - * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND.
823 - *
824 - * Copyright (C) 2002 Aleph One Ltd.
825 - * for Toby Churchill Ltd and Brightstar Engineering
826 - *
827 - * This program is free software; you can redistribute it and/or modify
828 - * it under the terms of the GNU General Public License version 2 as
829 - * published by the Free Software Foundation.
830 - */
831 -
832 -/*
833 - * This module provides the interface between yaffs_nand.c and the
834 - * MTD API. This version is used when the MTD interface supports the
835 - * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
836 - * and we have small-page NAND device.
837 - *
838 - * These functions are invoked via function pointers in yaffs_nand.c.
839 - * This replaces functionality provided by functions in yaffs_mtdif.c
840 - * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are
841 - * called in yaffs_mtdif.c when the function pointers are NULL.
842 - * We assume the MTD layer is performing ECC (useNANDECC is true).
843 - */
844 -
845 -#include "yportenv.h"
846 -#include "yaffs_guts.h"
847 -#include "yaffs_packedtags1.h"
848 -#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC
849 -
850 -#include "linux/kernel.h"
851 -#include "linux/version.h"
852 -#include "linux/types.h"
853 -#include "linux/mtd/mtd.h"
854 -
855 -/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
856 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
857 -
858 -const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1-compat.c 13022 2008-10-22 06:51:06Z nbd $";
859 -
860 -#ifndef CONFIG_YAFFS_9BYTE_TAGS
861 -# define YTAG1_SIZE 8
862 -#else
863 -# define YTAG1_SIZE 9
864 -#endif
865 -
866 -#if 0
867 -/* Use the following nand_ecclayout with MTD when using
868 - * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout.
869 - * If you have existing Yaffs images and the byte order differs from this,
870 - * adjust 'oobfree' to match your existing Yaffs data.
871 - *
872 - * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the
873 - * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to
874 - * the 9th byte.
875 - *
876 - * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5
877 - * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P
878 - * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus
879 - * byte and B is the small-page bad-block indicator byte.
880 - */
881 -static struct nand_ecclayout nand_oob_16 = {
882 - .eccbytes = 6,
883 - .eccpos = { 8, 9, 10, 13, 14, 15 },
884 - .oobavail = 9,
885 - .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
886 -};
887 -#endif
888 -
889 -/* Write a chunk (page) of data to NAND.
890 - *
891 - * Caller always provides ExtendedTags data which are converted to a more
892 - * compact (packed) form for storage in NAND. A mini-ECC runs over the
893 - * contents of the tags meta-data; used to valid the tags when read.
894 - *
895 - * - Pack ExtendedTags to PackedTags1 form
896 - * - Compute mini-ECC for PackedTags1
897 - * - Write data and packed tags to NAND.
898 - *
899 - * Note: Due to the use of the PackedTags1 meta-data which does not include
900 - * a full sequence number (as found in the larger PackedTags2 form) it is
901 - * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
902 - * discarded and dirty. This is not ideal: newer NAND parts are supposed
903 - * to be written just once. When Yaffs performs this operation, this
904 - * function is called with a NULL data pointer -- calling MTD write_oob
905 - * without data is valid usage (2.6.17).
906 - *
907 - * Any underlying MTD error results in YAFFS_FAIL.
908 - * Returns YAFFS_OK or YAFFS_FAIL.
909 - */
910 -int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
911 - int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags)
912 -{
913 - struct mtd_info * mtd = dev->genericDevice;
914 - int chunkBytes = dev->nDataBytesPerChunk;
915 - loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
916 - struct mtd_oob_ops ops;
917 - yaffs_PackedTags1 pt1;
918 - int retval;
919 -
920 - /* we assume that PackedTags1 and yaffs_Tags are compatible */
921 - compile_time_assertion(sizeof(yaffs_PackedTags1) == 12);
922 - compile_time_assertion(sizeof(yaffs_Tags) == 8);
923 -
924 - yaffs_PackTags1(&pt1, etags);
925 - yaffs_CalcTagsECC((yaffs_Tags *)&pt1);
926 -
927 - /* When deleting a chunk, the upper layer provides only skeletal
928 - * etags, one with chunkDeleted set. However, we need to update the
929 - * tags, not erase them completely. So we use the NAND write property
930 - * that only zeroed-bits stick and set tag bytes to all-ones and
931 - * zero just the (not) deleted bit.
932 - */
933 -#ifndef CONFIG_YAFFS_9BYTE_TAGS
934 - if (etags->chunkDeleted) {
935 - memset(&pt1, 0xff, 8);
936 - /* clear delete status bit to indicate deleted */
937 - pt1.deleted = 0;
938 - }
939 -#else
940 - ((__u8 *)&pt1)[8] = 0xff;
941 - if (etags->chunkDeleted) {
942 - memset(&pt1, 0xff, 8);
943 - /* zero pageStatus byte to indicate deleted */
944 - ((__u8 *)&pt1)[8] = 0;
945 - }
946 -#endif
947 -
948 - memset(&ops, 0, sizeof(ops));
949 - ops.mode = MTD_OOB_AUTO;
950 - ops.len = (data) ? chunkBytes : 0;
951 - ops.ooblen = YTAG1_SIZE;
952 - ops.datbuf = (__u8 *)data;
953 - ops.oobbuf = (__u8 *)&pt1;
954 -
955 - retval = mtd->write_oob(mtd, addr, &ops);
956 - if (retval) {
957 - yaffs_trace(YAFFS_TRACE_MTD,
958 - "write_oob failed, chunk %d, mtd error %d\n",
959 - chunkInNAND, retval);
960 - }
961 - return retval ? YAFFS_FAIL : YAFFS_OK;
962 -}
963 -
964 -/* Return with empty ExtendedTags but add eccResult.
965 - */
966 -static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval)
967 -{
968 - if (etags) {
969 - memset(etags, 0, sizeof(*etags));
970 - etags->eccResult = eccResult;
971 - }
972 - return retval;
973 -}
974 -
975 -/* Read a chunk (page) from NAND.
976 - *
977 - * Caller expects ExtendedTags data to be usable even on error; that is,
978 - * all members except eccResult and blockBad are zeroed.
979 - *
980 - * - Check ECC results for data (if applicable)
981 - * - Check for blank/erased block (return empty ExtendedTags if blank)
982 - * - Check the PackedTags1 mini-ECC (correct if necessary/possible)
983 - * - Convert PackedTags1 to ExtendedTags
984 - * - Update eccResult and blockBad members to refect state.
985 - *
986 - * Returns YAFFS_OK or YAFFS_FAIL.
987 - */
988 -int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
989 - int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags)
990 -{
991 - struct mtd_info * mtd = dev->genericDevice;
992 - int chunkBytes = dev->nDataBytesPerChunk;
993 - loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
994 - int eccres = YAFFS_ECC_RESULT_NO_ERROR;
995 - struct mtd_oob_ops ops;
996 - yaffs_PackedTags1 pt1;
997 - int retval;
998 - int deleted;
999 -
1000 - memset(&ops, 0, sizeof(ops));
1001 - ops.mode = MTD_OOB_AUTO;
1002 - ops.len = (data) ? chunkBytes : 0;
1003 - ops.ooblen = YTAG1_SIZE;
1004 - ops.datbuf = data;
1005 - ops.oobbuf = (__u8 *)&pt1;
1006 -
1007 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
1008 - /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
1009 - * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
1010 - */
1011 - ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
1012 -#endif
1013 - /* Read page and oob using MTD.
1014 - * Check status and determine ECC result.
1015 - */
1016 - retval = mtd->read_oob(mtd, addr, &ops);
1017 - if (retval) {
1018 - yaffs_trace(YAFFS_TRACE_MTD,
1019 - "read_oob failed, chunk %d, mtd error %d\n",
1020 - chunkInNAND, retval);
1021 - }
1022 -
1023 - switch (retval) {
1024 - case 0:
1025 - /* no error */
1026 - break;
1027 -
1028 - case -EUCLEAN:
1029 - /* MTD's ECC fixed the data */
1030 - eccres = YAFFS_ECC_RESULT_FIXED;
1031 - dev->eccFixed++;
1032 - break;
1033 -
1034 - case -EBADMSG:
1035 - /* MTD's ECC could not fix the data */
1036 - dev->eccUnfixed++;
1037 - /* fall into... */
1038 - default:
1039 - rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
1040 - etags->blockBad = (mtd->block_isbad)(mtd, addr);
1041 - return YAFFS_FAIL;
1042 - }
1043 -
1044 - /* Check for a blank/erased chunk.
1045 - */
1046 - if (yaffs_CheckFF((__u8 *)&pt1, 8)) {
1047 - /* when blank, upper layers want eccResult to be <= NO_ERROR */
1048 - return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
1049 - }
1050 -
1051 -#ifndef CONFIG_YAFFS_9BYTE_TAGS
1052 - /* Read deleted status (bit) then return it to it's non-deleted
1053 - * state before performing tags mini-ECC check. pt1.deleted is
1054 - * inverted.
1055 - */
1056 - deleted = !pt1.deleted;
1057 - pt1.deleted = 1;
1058 -#else
1059 - (void) deleted; /* not used */
1060 -#endif
1061 -
1062 - /* Check the packed tags mini-ECC and correct if necessary/possible.
1063 - */
1064 - retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1);
1065 - switch (retval) {
1066 - case 0:
1067 - /* no tags error, use MTD result */
1068 - break;
1069 - case 1:
1070 - /* recovered tags-ECC error */
1071 - dev->tagsEccFixed++;
1072 - eccres = YAFFS_ECC_RESULT_FIXED;
1073 - break;
1074 - default:
1075 - /* unrecovered tags-ECC error */
1076 - dev->tagsEccUnfixed++;
1077 - return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
1078 - }
1079 -
1080 - /* Unpack the tags to extended form and set ECC result.
1081 - * [set shouldBeFF just to keep yaffs_UnpackTags1 happy]
1082 - */
1083 - pt1.shouldBeFF = 0xFFFFFFFF;
1084 - yaffs_UnpackTags1(etags, &pt1);
1085 - etags->eccResult = eccres;
1086 -
1087 - /* Set deleted state.
1088 - */
1089 -#ifndef CONFIG_YAFFS_9BYTE_TAGS
1090 - etags->chunkDeleted = deleted;
1091 -#else
1092 - etags->chunkDeleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7);
1093 -#endif
1094 - return YAFFS_OK;
1095 -}
1096 -
1097 -/* Mark a block bad.
1098 - *
1099 - * This is a persistant state.
1100 - * Use of this function should be rare.
1101 - *
1102 - * Returns YAFFS_OK or YAFFS_FAIL.
1103 - */
1104 -int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
1105 -{
1106 - struct mtd_info * mtd = dev->genericDevice;
1107 - int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
1108 - int retval;
1109 -
1110 - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
1111 -
1112 - retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
1113 - return (retval) ? YAFFS_FAIL : YAFFS_OK;
1114 -}
1115 -
1116 -/* Check any MTD prerequists.
1117 - *
1118 - * Returns YAFFS_OK or YAFFS_FAIL.
1119 - */
1120 -static int nandmtd1_TestPrerequists(struct mtd_info * mtd)
1121 -{
1122 - /* 2.6.18 has mtd->ecclayout->oobavail */
1123 - /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
1124 - int oobavail = mtd->ecclayout->oobavail;
1125 -
1126 - if (oobavail < YTAG1_SIZE) {
1127 - yaffs_trace(YAFFS_TRACE_ERROR,
1128 - "mtd device has only %d bytes for tags, need %d",
1129 - oobavail, YTAG1_SIZE);
1130 - return YAFFS_FAIL;
1131 - }
1132 - return YAFFS_OK;
1133 -}
1134 -
1135 -/* Query for the current state of a specific block.
1136 - *
1137 - * Examine the tags of the first chunk of the block and return the state:
1138 - * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
1139 - * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use
1140 - * - YAFFS_BLOCK_STATE_EMPTY, the block is clean
1141 - *
1142 - * Always returns YAFFS_OK.
1143 - */
1144 -int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
1145 - yaffs_BlockState * pState, int *pSequenceNumber)
1146 -{
1147 - struct mtd_info * mtd = dev->genericDevice;
1148 - int chunkNo = blockNo * dev->nChunksPerBlock;
1149 - yaffs_ExtendedTags etags;
1150 - int state = YAFFS_BLOCK_STATE_DEAD;
1151 - int seqnum = 0;
1152 - int retval;
1153 -
1154 - /* We don't yet have a good place to test for MTD config prerequists.
1155 - * Do it here as we are called during the initial scan.
1156 - */
1157 - if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) {
1158 - return YAFFS_FAIL;
1159 - }
1160 -
1161 - retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
1162 - if (etags.blockBad) {
1163 - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
1164 - "block %d is marked bad", blockNo);
1165 - state = YAFFS_BLOCK_STATE_DEAD;
1166 - }
1167 - else if (etags.chunkUsed) {
1168 - state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
1169 - seqnum = etags.sequenceNumber;
1170 - }
1171 - else {
1172 - state = YAFFS_BLOCK_STATE_EMPTY;
1173 - }
1174 -
1175 - *pState = state;
1176 - *pSequenceNumber = seqnum;
1177 -
1178 - /* query always succeeds */
1179 - return YAFFS_OK;
1180 -}
1181 -
1182 -#endif /*KERNEL_VERSION*/
1183 -
1184 ---Boundary-00=_5LbTGmt62YoutxM--
1185 -
1186 -
1187 -
1188 --- a/fs/yaffs2/yaffs_fs.c
1189 +++ b/fs/yaffs2/yaffs_fs.c
1190 @@ -32,7 +32,7 @@
1191 */
1192
1193 const char *yaffs_fs_c_version =
1194 - "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $";
1195 + "$Id: yaffs_fs.c,v 1.71 2009-01-22 00:45:54 charles Exp $";
1196 extern const char *yaffs_guts_c_version;
1197
1198 #include <linux/version.h>
1199 @@ -43,7 +43,6 @@ extern const char *yaffs_guts_c_version;
1200 #include <linux/module.h>
1201 #include <linux/slab.h>
1202 #include <linux/init.h>
1203 -#include <linux/list.h>
1204 #include <linux/fs.h>
1205 #include <linux/proc_fs.h>
1206 #include <linux/smp_lock.h>
1207 @@ -53,6 +52,8 @@ extern const char *yaffs_guts_c_version;
1208 #include <linux/string.h>
1209 #include <linux/ctype.h>
1210
1211 +#include "asm/div64.h"
1212 +
1213 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1214
1215 #include <linux/statfs.h> /* Added NCB 15-8-2003 */
1216 @@ -76,6 +77,12 @@ extern const char *yaffs_guts_c_version;
1217
1218 #endif
1219
1220 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
1221 +#define YPROC_ROOT &proc_root
1222 +#else
1223 +#define YPROC_ROOT NULL
1224 +#endif
1225 +
1226 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1227 #define WRITE_SIZE_STR "writesize"
1228 #define WRITE_SIZE(mtd) (mtd)->writesize
1229 @@ -84,6 +91,13 @@ extern const char *yaffs_guts_c_version;
1230 #define WRITE_SIZE(mtd) (mtd)->oobblock
1231 #endif
1232
1233 +#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
1234 +#define YAFFS_USE_WRITE_BEGIN_END 1
1235 +#else
1236 +#define YAFFS_USE_WRITE_BEGIN_END 0
1237 +#endif
1238 +
1239 +
1240 #include <asm/uaccess.h>
1241
1242 #include "yportenv.h"
1243 @@ -96,14 +110,30 @@ extern const char *yaffs_guts_c_version;
1244
1245 unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;
1246 unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
1247 +unsigned int yaffs_auto_checkpoint = 1;
1248
1249 /* Module Parameters */
1250 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
1251 module_param(yaffs_traceMask,uint,0644);
1252 module_param(yaffs_wr_attempts,uint,0644);
1253 +module_param(yaffs_auto_checkpoint,uint,0644);
1254 #else
1255 MODULE_PARM(yaffs_traceMask,"i");
1256 MODULE_PARM(yaffs_wr_attempts,"i");
1257 +MODULE_PARM(yaffs_auto_checkpoint,"i");
1258 +#endif
1259 +
1260 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
1261 +/* use iget and read_inode */
1262 +#define Y_IGET(sb,inum) iget((sb),(inum))
1263 +static void yaffs_read_inode(struct inode *inode);
1264 +
1265 +#else
1266 +/* Call local equivalent */
1267 +#define YAFFS_USE_OWN_IGET
1268 +#define Y_IGET(sb,inum) yaffs_iget((sb),(inum))
1269 +
1270 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino);
1271 #endif
1272
1273 /*#define T(x) printk x */
1274 @@ -127,6 +157,8 @@ static void yaffs_put_super(struct super
1275
1276 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
1277 loff_t * pos);
1278 +static ssize_t yaffs_hold_space(struct file *f);
1279 +static void yaffs_release_space(struct file *f);
1280
1281 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1282 static int yaffs_file_flush(struct file *file, fl_owner_t id);
1283 @@ -181,9 +213,11 @@ static int yaffs_statfs(struct super_blo
1284 #else
1285 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
1286 #endif
1287 -static void yaffs_read_inode(struct inode *inode);
1288
1289 +#ifdef YAFFS_HAS_PUT_INODE
1290 static void yaffs_put_inode(struct inode *inode);
1291 +#endif
1292 +
1293 static void yaffs_delete_inode(struct inode *);
1294 static void yaffs_clear_inode(struct inode *);
1295
1296 @@ -193,10 +227,22 @@ static int yaffs_writepage(struct page *
1297 #else
1298 static int yaffs_writepage(struct page *page);
1299 #endif
1300 +
1301 +
1302 +#if (YAFFS_USE_WRITE_BEGIN_END != 0)
1303 +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
1304 + loff_t pos, unsigned len, unsigned flags,
1305 + struct page **pagep, void **fsdata);
1306 +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
1307 + loff_t pos, unsigned len, unsigned copied,
1308 + struct page *pg, void *fsdadata);
1309 +#else
1310 static int yaffs_prepare_write(struct file *f, struct page *pg,
1311 unsigned offset, unsigned to);
1312 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
1313 unsigned to);
1314 +
1315 +#endif
1316
1317 static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
1318 int buflen);
1319 @@ -209,8 +255,13 @@ static int yaffs_follow_link(struct dent
1320 static struct address_space_operations yaffs_file_address_operations = {
1321 .readpage = yaffs_readpage,
1322 .writepage = yaffs_writepage,
1323 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
1324 + .write_begin = yaffs_write_begin,
1325 + .write_end = yaffs_write_end,
1326 +#else
1327 .prepare_write = yaffs_prepare_write,
1328 .commit_write = yaffs_commit_write,
1329 +#endif
1330 };
1331
1332 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
1333 @@ -224,6 +275,7 @@ static struct file_operations yaffs_file
1334 .fsync = yaffs_sync_object,
1335 .splice_read = generic_file_splice_read,
1336 .splice_write = generic_file_splice_write,
1337 + .llseek = generic_file_llseek,
1338 };
1339
1340 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
1341 @@ -284,8 +336,13 @@ static struct file_operations yaffs_dir_
1342
1343 static struct super_operations yaffs_super_ops = {
1344 .statfs = yaffs_statfs,
1345 +
1346 +#ifndef YAFFS_USE_OWN_IGET
1347 .read_inode = yaffs_read_inode,
1348 +#endif
1349 +#ifdef YAFFS_HAS_PUT_INODE
1350 .put_inode = yaffs_put_inode,
1351 +#endif
1352 .put_super = yaffs_put_super,
1353 .delete_inode = yaffs_delete_inode,
1354 .clear_inode = yaffs_clear_inode,
1355 @@ -429,6 +486,9 @@ static struct dentry *yaffs_lookup(struc
1356
1357 }
1358
1359 +
1360 +#ifdef YAFFS_HAS_PUT_INODE
1361 +
1362 /* For now put inode is just for debugging
1363 * Put inode is called when the inode **structure** is put.
1364 */
1365 @@ -439,6 +499,7 @@ static void yaffs_put_inode(struct inode
1366 atomic_read(&inode->i_count)));
1367
1368 }
1369 +#endif
1370
1371 /* clear is called to tell the fs to release any per-inode data it holds */
1372 static void yaffs_clear_inode(struct inode *inode)
1373 @@ -667,6 +728,64 @@ static int yaffs_writepage(struct page *
1374 return (nWritten == nBytes) ? 0 : -ENOSPC;
1375 }
1376
1377 +
1378 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
1379 +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
1380 + loff_t pos, unsigned len, unsigned flags,
1381 + struct page **pagep, void **fsdata)
1382 +
1383 +{
1384 + struct page *pg = NULL;
1385 + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1386 + uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
1387 + uint32_t to = offset + len;
1388 +
1389 + int ret = 0;
1390 + int space_held = 0;
1391 +
1392 + T(YAFFS_TRACE_OS, (KERN_DEBUG "start yaffs_write_begin\n"));
1393 + /* Get a page */
1394 + pg = __grab_cache_page(mapping,index);
1395 + *pagep = pg;
1396 + if(!pg){
1397 + ret = -ENOMEM;
1398 + goto out;
1399 + }
1400 + /* Get fs space */
1401 + space_held = yaffs_hold_space(filp);
1402 +
1403 + if(!space_held){
1404 + ret = -ENOSPC;
1405 + goto out;
1406 + }
1407 +
1408 + /* Update page if required */
1409 +
1410 + if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
1411 + ret = yaffs_readpage_nolock(filp, pg);
1412 +
1413 + if(ret)
1414 + goto out;
1415 +
1416 + /* Happy path return */
1417 + T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin - ok\n"));
1418 +
1419 + return 0;
1420 +
1421 +out:
1422 + T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin fail returning %d\n",ret));
1423 + if(space_held){
1424 + yaffs_release_space(filp);
1425 + }
1426 + if(pg) {
1427 + unlock_page(pg);
1428 + page_cache_release(pg);
1429 + }
1430 + return ret;
1431 +}
1432 +
1433 +#else
1434 +
1435 static int yaffs_prepare_write(struct file *f, struct page *pg,
1436 unsigned offset, unsigned to)
1437 {
1438 @@ -674,22 +793,69 @@ static int yaffs_prepare_write(struct fi
1439 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));
1440 if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
1441 return yaffs_readpage_nolock(f, pg);
1442 -
1443 return 0;
1444
1445 }
1446 +#endif
1447 +
1448 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
1449 +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
1450 + loff_t pos, unsigned len, unsigned copied,
1451 + struct page *pg, void *fsdadata)
1452 +{
1453 + int ret = 0;
1454 + void *addr, *kva;
1455 + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1456 + uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE -1);
1457 +
1458 +
1459 +
1460 + kva=kmap(pg);
1461 + addr = kva + offset_into_page;
1462 +
1463 + T(YAFFS_TRACE_OS,
1464 + (KERN_DEBUG "yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned) addr,
1465 + (int)pos, copied));
1466 +
1467 + ret = yaffs_file_write(filp, addr, copied, &pos);
1468 +
1469 + if (ret != copied) {
1470 + T(YAFFS_TRACE_OS,
1471 + (KERN_DEBUG
1472 + "yaffs_write_end not same size ret %d copied %d\n",
1473 + ret, copied ));
1474 + SetPageError(pg);
1475 + ClearPageUptodate(pg);
1476 + } else {
1477 + SetPageUptodate(pg);
1478 + }
1479 +
1480 + kunmap(pg);
1481 +
1482 + yaffs_release_space(filp);
1483 + unlock_page(pg);
1484 + page_cache_release(pg);
1485 + return ret;
1486 +}
1487 +#else
1488
1489 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
1490 unsigned to)
1491 {
1492
1493 - void *addr = page_address(pg) + offset;
1494 + void *addr, *kva;
1495 +
1496 loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
1497 int nBytes = to - offset;
1498 int nWritten;
1499
1500 unsigned spos = pos;
1501 - unsigned saddr = (unsigned)addr;
1502 + unsigned saddr;
1503 +
1504 + kva=kmap(pg);
1505 + addr = kva + offset;
1506 +
1507 + saddr = (unsigned) addr;
1508
1509 T(YAFFS_TRACE_OS,
1510 (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr,
1511 @@ -708,6 +874,8 @@ static int yaffs_commit_write(struct fil
1512 SetPageUptodate(pg);
1513 }
1514
1515 + kunmap(pg);
1516 +
1517 T(YAFFS_TRACE_OS,
1518 (KERN_DEBUG "yaffs_commit_write returning %d\n",
1519 nWritten == nBytes ? 0 : nWritten));
1520 @@ -715,6 +883,8 @@ static int yaffs_commit_write(struct fil
1521 return nWritten == nBytes ? 0 : nWritten;
1522
1523 }
1524 +#endif
1525 +
1526
1527 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
1528 {
1529 @@ -753,6 +923,8 @@ static void yaffs_FillInodeFromObject(st
1530 break;
1531 }
1532
1533 + inode->i_flags |= S_NOATIME;
1534 +
1535 inode->i_ino = obj->objectId;
1536 inode->i_mode = obj->yst_mode;
1537 inode->i_uid = obj->yst_uid;
1538 @@ -844,7 +1016,9 @@ struct inode *yaffs_get_inode(struct sup
1539 T(YAFFS_TRACE_OS,
1540 (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
1541
1542 - inode = iget(sb, obj->objectId);
1543 + inode = Y_IGET(sb, obj->objectId);
1544 + if(IS_ERR(inode))
1545 + return NULL;
1546
1547 /* NB Side effect: iget calls back to yaffs_read_inode(). */
1548 /* iget also increments the inode's i_count */
1549 @@ -910,13 +1084,55 @@ static ssize_t yaffs_file_write(struct f
1550 return nWritten == 0 ? -ENOSPC : nWritten;
1551 }
1552
1553 +/* Space holding and freeing is done to ensure we have space available for write_begin/end */
1554 +/* For now we just assume few parallel writes and check against a small number. */
1555 +/* Todo: need to do this with a counter to handle parallel reads better */
1556 +
1557 +static ssize_t yaffs_hold_space(struct file *f)
1558 +{
1559 + yaffs_Object *obj;
1560 + yaffs_Device *dev;
1561 +
1562 + int nFreeChunks;
1563 +
1564 +
1565 + obj = yaffs_DentryToObject(f->f_dentry);
1566 +
1567 + dev = obj->myDev;
1568 +
1569 + yaffs_GrossLock(dev);
1570 +
1571 + nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
1572 +
1573 + yaffs_GrossUnlock(dev);
1574 +
1575 + return (nFreeChunks > 20) ? 1 : 0;
1576 +}
1577 +
1578 +static void yaffs_release_space(struct file *f)
1579 +{
1580 + yaffs_Object *obj;
1581 + yaffs_Device *dev;
1582 +
1583 +
1584 + obj = yaffs_DentryToObject(f->f_dentry);
1585 +
1586 + dev = obj->myDev;
1587 +
1588 + yaffs_GrossLock(dev);
1589 +
1590 +
1591 + yaffs_GrossUnlock(dev);
1592 +
1593 +}
1594 +
1595 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
1596 {
1597 yaffs_Object *obj;
1598 yaffs_Device *dev;
1599 struct inode *inode = f->f_dentry->d_inode;
1600 unsigned long offset, curoffs;
1601 - struct list_head *i;
1602 + struct ylist_head *i;
1603 yaffs_Object *l;
1604
1605 char name[YAFFS_MAX_NAME_LENGTH + 1];
1606 @@ -965,10 +1181,10 @@ static int yaffs_readdir(struct file *f,
1607 f->f_version = inode->i_version;
1608 }
1609
1610 - list_for_each(i, &obj->variant.directoryVariant.children) {
1611 + ylist_for_each(i, &obj->variant.directoryVariant.children) {
1612 curoffs++;
1613 if (curoffs >= offset) {
1614 - l = list_entry(i, yaffs_Object, siblings);
1615 + l = ylist_entry(i, yaffs_Object, siblings);
1616
1617 yaffs_GetObjectName(l, name,
1618 YAFFS_MAX_NAME_LENGTH + 1);
1619 @@ -1269,7 +1485,7 @@ static int yaffs_rename(struct inode *ol
1620
1621 if (target &&
1622 target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
1623 - !list_empty(&target->variant.directoryVariant.children)) {
1624 + !ylist_empty(&target->variant.directoryVariant.children)) {
1625
1626 T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
1627
1628 @@ -1350,25 +1566,47 @@ static int yaffs_statfs(struct super_blo
1629 buf->f_type = YAFFS_MAGIC;
1630 buf->f_bsize = sb->s_blocksize;
1631 buf->f_namelen = 255;
1632 - if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1633 -
1634 +
1635 + if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
1636 + /* Do this if chunk size is not a power of 2 */
1637 +
1638 + uint64_t bytesInDev;
1639 + uint64_t bytesFree;
1640 +
1641 + bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
1642 + ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
1643 +
1644 + do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
1645 + buf->f_blocks = bytesInDev;
1646 +
1647 + bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
1648 + ((uint64_t)(dev->nDataBytesPerChunk));
1649 +
1650 + do_div(bytesFree,sb->s_blocksize);
1651 +
1652 + buf->f_bfree = bytesFree;
1653 +
1654 + } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1655 +
1656 buf->f_blocks =
1657 - (dev->endBlock - dev->startBlock +
1658 - 1) * dev->nChunksPerBlock / (sb->s_blocksize /
1659 - dev->nDataBytesPerChunk);
1660 - buf->f_bfree =
1661 - yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
1662 - dev->nDataBytesPerChunk);
1663 + (dev->endBlock - dev->startBlock + 1) *
1664 + dev->nChunksPerBlock /
1665 + (sb->s_blocksize / dev->nDataBytesPerChunk);
1666 + buf->f_bfree =
1667 + yaffs_GetNumberOfFreeChunks(dev) /
1668 + (sb->s_blocksize / dev->nDataBytesPerChunk);
1669 } else {
1670 -
1671 - buf->f_blocks =
1672 - (dev->endBlock - dev->startBlock +
1673 - 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
1674 - sb->s_blocksize);
1675 - buf->f_bfree =
1676 - yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
1677 - sb->s_blocksize);
1678 + buf->f_blocks =
1679 + (dev->endBlock - dev->startBlock + 1) *
1680 + dev->nChunksPerBlock *
1681 + (dev->nDataBytesPerChunk / sb->s_blocksize);
1682 +
1683 + buf->f_bfree =
1684 + yaffs_GetNumberOfFreeChunks(dev) *
1685 + (dev->nDataBytesPerChunk / sb->s_blocksize);
1686 }
1687 +
1688 +
1689 buf->f_files = 0;
1690 buf->f_ffree = 0;
1691 buf->f_bavail = buf->f_bfree;
1692 @@ -1378,7 +1616,6 @@ static int yaffs_statfs(struct super_blo
1693 }
1694
1695
1696 -/**
1697 static int yaffs_do_sync_fs(struct super_block *sb)
1698 {
1699
1700 @@ -1388,8 +1625,10 @@ static int yaffs_do_sync_fs(struct super
1701 if(sb->s_dirt) {
1702 yaffs_GrossLock(dev);
1703
1704 - if(dev)
1705 + if(dev){
1706 + yaffs_FlushEntireDeviceCache(dev);
1707 yaffs_CheckpointSave(dev);
1708 + }
1709
1710 yaffs_GrossUnlock(dev);
1711
1712 @@ -1397,7 +1636,7 @@ static int yaffs_do_sync_fs(struct super
1713 }
1714 return 0;
1715 }
1716 -**/
1717 +
1718
1719 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1720 static void yaffs_write_super(struct super_block *sb)
1721 @@ -1407,8 +1646,10 @@ static int yaffs_write_super(struct supe
1722 {
1723
1724 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
1725 + if (yaffs_auto_checkpoint >= 2)
1726 + yaffs_do_sync_fs(sb);
1727 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
1728 - return 0; /* yaffs_do_sync_fs(sb);*/
1729 + return 0;
1730 #endif
1731 }
1732
1733 @@ -1422,10 +1663,48 @@ static int yaffs_sync_fs(struct super_bl
1734
1735 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
1736
1737 - return 0; /* yaffs_do_sync_fs(sb);*/
1738 + if (yaffs_auto_checkpoint >= 1)
1739 + yaffs_do_sync_fs(sb);
1740 +
1741 + return 0;
1742
1743 }
1744
1745 +#ifdef YAFFS_USE_OWN_IGET
1746 +
1747 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino)
1748 +{
1749 + struct inode *inode;
1750 + yaffs_Object *obj;
1751 + yaffs_Device *dev = yaffs_SuperToDevice(sb);
1752 +
1753 + T(YAFFS_TRACE_OS,
1754 + (KERN_DEBUG "yaffs_iget for %lu\n", ino));
1755 +
1756 + inode = iget_locked(sb, ino);
1757 + if (!inode)
1758 + return ERR_PTR(-ENOMEM);
1759 + if (!(inode->i_state & I_NEW))
1760 + return inode;
1761 +
1762 + /* NB This is called as a side effect of other functions, but
1763 + * we had to release the lock to prevent deadlocks, so
1764 + * need to lock again.
1765 + */
1766 +
1767 + yaffs_GrossLock(dev);
1768 +
1769 + obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
1770 +
1771 + yaffs_FillInodeFromObject(inode, obj);
1772 +
1773 + yaffs_GrossUnlock(dev);
1774 +
1775 + unlock_new_inode(inode);
1776 + return inode;
1777 +}
1778 +
1779 +#else
1780
1781 static void yaffs_read_inode(struct inode *inode)
1782 {
1783 @@ -1449,7 +1728,9 @@ static void yaffs_read_inode(struct inod
1784 yaffs_GrossUnlock(dev);
1785 }
1786
1787 -static LIST_HEAD(yaffs_dev_list);
1788 +#endif
1789 +
1790 +static YLIST_HEAD(yaffs_dev_list);
1791
1792 #if 0 // not used
1793 static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
1794 @@ -1503,7 +1784,7 @@ static void yaffs_put_super(struct super
1795 yaffs_GrossUnlock(dev);
1796
1797 /* we assume this is protected by lock_kernel() in mount/umount */
1798 - list_del(&dev->devList);
1799 + ylist_del(&dev->devList);
1800
1801 if(dev->spareBuffer){
1802 YFREE(dev->spareBuffer);
1803 @@ -1532,8 +1813,8 @@ static void yaffs_MarkSuperBlockDirty(vo
1804 struct super_block *sb = (struct super_block *)vsb;
1805
1806 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb));
1807 -// if(sb)
1808 -// sb->s_dirt = 1;
1809 + if(sb)
1810 + sb->s_dirt = 1;
1811 }
1812
1813 typedef struct {
1814 @@ -1602,6 +1883,7 @@ static struct super_block *yaffs_interna
1815
1816 sb->s_magic = YAFFS_MAGIC;
1817 sb->s_op = &yaffs_super_ops;
1818 + sb->s_flags |= MS_NOATIME;
1819
1820 if (!sb)
1821 printk(KERN_INFO "yaffs: sb is NULL\n");
1822 @@ -1678,22 +1960,15 @@ static struct super_block *yaffs_interna
1823 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
1824
1825 if (yaffsVersion == 1 &&
1826 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1827 - mtd->writesize >= 2048) {
1828 -#else
1829 - mtd->oobblock >= 2048) {
1830 -#endif
1831 + WRITE_SIZE(mtd) >= 2048) {
1832 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
1833 yaffsVersion = 2;
1834 }
1835
1836 /* Added NCB 26/5/2006 for completeness */
1837 - if (yaffsVersion == 2 &&
1838 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1839 - mtd->writesize == 512) {
1840 -#else
1841 - mtd->oobblock == 512) {
1842 -#endif
1843 + if (yaffsVersion == 2 &&
1844 + !options.inband_tags &&
1845 + WRITE_SIZE(mtd) == 512){
1846 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
1847 yaffsVersion = 1;
1848 }
1849 @@ -1719,12 +1994,9 @@ static struct super_block *yaffs_interna
1850 return NULL;
1851 }
1852
1853 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1854 - if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1855 -#else
1856 - if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1857 -#endif
1858 - mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
1859 + if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1860 + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
1861 + !options.inband_tags) {
1862 T(YAFFS_TRACE_ALWAYS,
1863 ("yaffs: MTD device does not have the "
1864 "right page sizes\n"));
1865 @@ -1784,9 +2056,10 @@ static struct super_block *yaffs_interna
1866 dev->startBlock = 0;
1867 dev->endBlock = nBlocks - 1;
1868 dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
1869 - dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
1870 + dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
1871 dev->nReservedBlocks = 5;
1872 dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
1873 + dev->inbandTags = options.inband_tags;
1874
1875 /* ... and the functions. */
1876 if (yaffsVersion == 2) {
1877 @@ -1799,15 +2072,14 @@ static struct super_block *yaffs_interna
1878 dev->spareBuffer = YMALLOC(mtd->oobsize);
1879 dev->isYaffs2 = 1;
1880 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1881 - dev->nDataBytesPerChunk = mtd->writesize;
1882 + dev->totalBytesPerChunk = mtd->writesize;
1883 dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
1884 #else
1885 - dev->nDataBytesPerChunk = mtd->oobblock;
1886 + dev->totalBytesPerChunk = mtd->oobblock;
1887 dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
1888 #endif
1889 nBlocks = mtd->size / mtd->erasesize;
1890
1891 - dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;
1892 dev->startBlock = 0;
1893 dev->endBlock = nBlocks - 1;
1894 } else {
1895 @@ -1847,7 +2119,7 @@ static struct super_block *yaffs_interna
1896 dev->skipCheckpointWrite = options.skip_checkpoint_write;
1897
1898 /* we assume this is protected by lock_kernel() in mount/umount */
1899 - list_add_tail(&dev->devList, &yaffs_dev_list);
1900 + ylist_add_tail(&dev->devList, &yaffs_dev_list);
1901
1902 init_MUTEX(&dev->grossLock);
1903
1904 @@ -1884,6 +2156,9 @@ static struct super_block *yaffs_interna
1905 return NULL;
1906 }
1907 sb->s_root = root;
1908 + sb->s_dirt = !dev->isCheckpointed;
1909 + T(YAFFS_TRACE_ALWAYS,
1910 + ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));
1911
1912 T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
1913 return sb;
1914 @@ -1990,12 +2265,12 @@ static char *yaffs_dump_dev(char *buf, y
1915 {
1916 buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
1917 buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
1918 + buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);
1919 buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);
1920 buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
1921 buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
1922 buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
1923 buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks);
1924 - buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks);
1925 buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);
1926 buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
1927 buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
1928 @@ -2006,10 +2281,8 @@ static char *yaffs_dump_dev(char *buf, y
1929 buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
1930 buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
1931 buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
1932 - buf +=
1933 - sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1934 - buf +=
1935 - sprintf(buf, "passiveGCs......... %d\n",
1936 + buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1937 + buf += sprintf(buf, "passiveGCs......... %d\n",
1938 dev->passiveGarbageCollections);
1939 buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
1940 buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches);
1941 @@ -2025,6 +2298,7 @@ static char *yaffs_dump_dev(char *buf, y
1942 sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
1943 buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
1944 buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
1945 + buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
1946
1947 return buf;
1948 }
1949 @@ -2033,7 +2307,7 @@ static int yaffs_proc_read(char *page,
1950 char **start,
1951 off_t offset, int count, int *eof, void *data)
1952 {
1953 - struct list_head *item;
1954 + struct ylist_head *item;
1955 char *buf = page;
1956 int step = offset;
1957 int n = 0;
1958 @@ -2057,8 +2331,8 @@ static int yaffs_proc_read(char *page,
1959 lock_kernel();
1960
1961 /* Locate and print the Nth entry. Order N-squared but N is small. */
1962 - list_for_each(item, &yaffs_dev_list) {
1963 - yaffs_Device *dev = list_entry(item, yaffs_Device, devList);
1964 + ylist_for_each(item, &yaffs_dev_list) {
1965 + yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList);
1966 if (n < step) {
1967 n++;
1968 continue;
1969 @@ -2231,7 +2505,7 @@ static int __init init_yaffs_fs(void)
1970 /* Install the proc_fs entry */
1971 my_proc_entry = create_proc_entry("yaffs",
1972 S_IRUGO | S_IFREG,
1973 - &proc_root);
1974 + YPROC_ROOT);
1975
1976 if (my_proc_entry) {
1977 my_proc_entry->write_proc = yaffs_proc_write;
1978 @@ -2277,7 +2551,7 @@ static void __exit exit_yaffs_fs(void)
1979 T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__
1980 " removing. \n"));
1981
1982 - remove_proc_entry("yaffs", &proc_root);
1983 + remove_proc_entry("yaffs", YPROC_ROOT);
1984
1985 fsinst = fs_to_install;
1986
1987 --- /dev/null
1988 +++ b/fs/yaffs2/yaffs_getblockinfo.h
1989 @@ -0,0 +1,34 @@
1990 +/*
1991 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
1992 + *
1993 + * Copyright (C) 2002-2007 Aleph One Ltd.
1994 + * for Toby Churchill Ltd and Brightstar Engineering
1995 + *
1996 + * Created by Charles Manning <charles@aleph1.co.uk>
1997 + *
1998 + * This program is free software; you can redistribute it and/or modify
1999 + * it under the terms of the GNU Lesser General Public License version 2.1 as
2000 + * published by the Free Software Foundation.
2001 + *
2002 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
2003 + */
2004 +
2005 +#ifndef __YAFFS_GETBLOCKINFO_H__
2006 +#define __YAFFS_GETBLOCKINFO_H__
2007 +
2008 +#include "yaffs_guts.h"
2009 +
2010 +/* Function to manipulate block info */
2011 +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
2012 +{
2013 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
2014 + T(YAFFS_TRACE_ERROR,
2015 + (TSTR
2016 + ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
2017 + blk));
2018 + YBUG();
2019 + }
2020 + return &dev->blockInfo[blk - dev->internalStartBlock];
2021 +}
2022 +
2023 +#endif
2024 --- a/fs/yaffs2/yaffs_nand.c
2025 +++ b/fs/yaffs2/yaffs_nand.c
2026 @@ -12,12 +12,13 @@
2027 */
2028
2029 const char *yaffs_nand_c_version =
2030 - "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $";
2031 + "$Id: yaffs_nand.c,v 1.9 2008-05-05 07:58:58 charles Exp $";
2032
2033 #include "yaffs_nand.h"
2034 #include "yaffs_tagscompat.h"
2035 #include "yaffs_tagsvalidity.h"
2036
2037 +#include "yaffs_getblockinfo.h"
2038
2039 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
2040 __u8 * buffer,
2041 @@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * de
2042 int yaffs_QueryInitialBlockState(yaffs_Device * dev,
2043 int blockNo,
2044 yaffs_BlockState * state,
2045 - unsigned *sequenceNumber)
2046 + __u32 *sequenceNumber)
2047 {
2048 blockNo -= dev->blockOffset;
2049
2050 --- a/fs/yaffs2/yaffs_guts.c
2051 +++ b/fs/yaffs2/yaffs_guts.c
2052 @@ -11,14 +11,16 @@
2053 * published by the Free Software Foundation.
2054 */
2055
2056 +
2057 const char *yaffs_guts_c_version =
2058 - "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $";
2059 + "$Id: yaffs_guts.c,v 1.76 2009-01-23 06:36:49 charles Exp $";
2060
2061 #include "yportenv.h"
2062
2063 #include "yaffsinterface.h"
2064 #include "yaffs_guts.h"
2065 #include "yaffs_tagsvalidity.h"
2066 +#include "yaffs_getblockinfo.h"
2067
2068 #include "yaffs_tagscompat.h"
2069 #ifndef CONFIG_YAFFS_USE_OWN_SORT
2070 @@ -32,11 +34,6 @@ const char *yaffs_guts_c_version =
2071 #include "yaffs_packedtags2.h"
2072
2073
2074 -#ifdef CONFIG_YAFFS_WINCE
2075 -void yfsd_LockYAFFS(BOOL fsLockOnly);
2076 -void yfsd_UnlockYAFFS(BOOL fsLockOnly);
2077 -#endif
2078 -
2079 #define YAFFS_PASSIVE_GC_CHUNKS 2
2080
2081 #include "yaffs_ecc.h"
2082 @@ -78,9 +75,6 @@ static int yaffs_DoGenericObjectDeletion
2083
2084 static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
2085
2086 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
2087 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
2088 - int lineNo);
2089
2090 static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
2091 int chunkInNAND);
2092 @@ -99,6 +93,7 @@ static void yaffs_VerifyFreeChunks(yaffs
2093
2094 static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
2095
2096 +static void yaffs_VerifyDirectory(yaffs_Object *directory);
2097 #ifdef YAFFS_PARANOID
2098 static int yaffs_CheckFileSanity(yaffs_Object * in);
2099 #else
2100 @@ -121,95 +116,109 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
2101
2102 /* Function to calculate chunk and offset */
2103
2104 -static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
2105 +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
2106 {
2107 - if(dev->chunkShift){
2108 - /* Easy-peasy power of 2 case */
2109 - *chunk = (__u32)(addr >> dev->chunkShift);
2110 - *offset = (__u32)(addr & dev->chunkMask);
2111 - }
2112 - else if(dev->crumbsPerChunk)
2113 + int chunk;
2114 + __u32 offset;
2115 +
2116 + chunk = (__u32)(addr >> dev->chunkShift);
2117 +
2118 + if(dev->chunkDiv == 1)
2119 {
2120 - /* Case where we're using "crumbs" */
2121 - *offset = (__u32)(addr & dev->crumbMask);
2122 - addr >>= dev->crumbShift;
2123 - *chunk = ((__u32)addr)/dev->crumbsPerChunk;
2124 - *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
2125 + /* easy power of 2 case */
2126 + offset = (__u32)(addr & dev->chunkMask);
2127 }
2128 else
2129 - YBUG();
2130 + {
2131 + /* Non power-of-2 case */
2132 +
2133 + loff_t chunkBase;
2134 +
2135 + chunk /= dev->chunkDiv;
2136 +
2137 + chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
2138 + offset = (__u32)(addr - chunkBase);
2139 + }
2140 +
2141 + *chunkOut = chunk;
2142 + *offsetOut = offset;
2143 }
2144
2145 -/* Function to return the number of shifts for a power of 2 greater than or equal
2146 +/* Function to return the number of shifts for a power of 2 greater than or equal
2147 * to the given number
2148 * Note we don't try to cater for all possible numbers and this does not have to
2149 * be hellishly efficient.
2150 */
2151 -
2152 +
2153 static __u32 ShiftsGE(__u32 x)
2154 {
2155 int extraBits;
2156 int nShifts;
2157 -
2158 +
2159 nShifts = extraBits = 0;
2160 -
2161 +
2162 while(x>1){
2163 if(x & 1) extraBits++;
2164 x>>=1;
2165 nShifts++;
2166 }
2167
2168 - if(extraBits)
2169 + if(extraBits)
2170 nShifts++;
2171 -
2172 +
2173 return nShifts;
2174 }
2175
2176 /* Function to return the number of shifts to get a 1 in bit 0
2177 */
2178 -
2179 -static __u32 ShiftDiv(__u32 x)
2180 +
2181 +static __u32 Shifts(__u32 x)
2182 {
2183 int nShifts;
2184 -
2185 +
2186 nShifts = 0;
2187 -
2188 +
2189 if(!x) return 0;
2190 -
2191 +
2192 while( !(x&1)){
2193 x>>=1;
2194 nShifts++;
2195 }
2196 -
2197 +
2198 return nShifts;
2199 }
2200
2201
2202
2203 -/*
2204 +/*
2205 * Temporary buffer manipulations.
2206 */
2207
2208 -static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
2209 +static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
2210 {
2211 int i;
2212 __u8 *buf = (__u8 *)1;
2213 -
2214 +
2215 memset(dev->tempBuffer,0,sizeof(dev->tempBuffer));
2216 -
2217 +
2218 for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
2219 dev->tempBuffer[i].line = 0; /* not in use */
2220 dev->tempBuffer[i].buffer = buf =
2221 - YMALLOC_DMA(dev->nDataBytesPerChunk);
2222 + YMALLOC_DMA(dev->totalBytesPerChunk);
2223 }
2224 -
2225 +
2226 return buf ? YAFFS_OK : YAFFS_FAIL;
2227 -
2228 +
2229 }
2230
2231 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
2232 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
2233 {
2234 int i, j;
2235 +
2236 + dev->tempInUse++;
2237 + if(dev->tempInUse > dev->maxTemp)
2238 + dev->maxTemp = dev->tempInUse;
2239 +
2240 for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
2241 if (dev->tempBuffer[i].line == 0) {
2242 dev->tempBuffer[i].line = lineNo;
2243 @@ -242,10 +251,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D
2244
2245 }
2246
2247 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
2248 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
2249 int lineNo)
2250 {
2251 int i;
2252 +
2253 + dev->tempInUse--;
2254 +
2255 for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
2256 if (dev->tempBuffer[i].buffer == buffer) {
2257 dev->tempBuffer[i].line = 0;
2258 @@ -337,7 +349,7 @@ static Y_INLINE void yaffs_ClearChunkBit
2259 static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
2260 {
2261 __u8 *blkBits = yaffs_BlockBits(dev, blk);
2262 -
2263 +
2264 yaffs_VerifyChunkBitId(dev,blk,chunk);
2265
2266 blkBits[chunk / 8] |= (1 << (chunk & 7));
2267 @@ -375,16 +387,16 @@ static int yaffs_CountChunkBits(yaffs_De
2268 n++;
2269 x >>=1;
2270 }
2271 -
2272 +
2273 blkBits++;
2274 }
2275 return n;
2276 }
2277
2278 -/*
2279 +/*
2280 * Verification code
2281 */
2282 -
2283 +
2284 static int yaffs_SkipVerification(yaffs_Device *dev)
2285 {
2286 return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
2287 @@ -417,14 +429,14 @@ static void yaffs_VerifyBlock(yaffs_Devi
2288 {
2289 int actuallyUsed;
2290 int inUse;
2291 -
2292 +
2293 if(yaffs_SkipVerification(dev))
2294 return;
2295 -
2296 +
2297 /* Report illegal runtime states */
2298 - if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
2299 + if(bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
2300 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState));
2301 -
2302 +
2303 switch(bi->blockState){
2304 case YAFFS_BLOCK_STATE_UNKNOWN:
2305 case YAFFS_BLOCK_STATE_SCANNING:
2306 @@ -432,43 +444,44 @@ static void yaffs_VerifyBlock(yaffs_Devi
2307 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR),
2308 n,blockStateName[bi->blockState]));
2309 }
2310 -
2311 +
2312 /* Check pages in use and soft deletions are legal */
2313 -
2314 +
2315 actuallyUsed = bi->pagesInUse - bi->softDeletions;
2316 -
2317 +
2318 if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock ||
2319 bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock ||
2320 actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock)
2321 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR),
2322 n,bi->pagesInUse,bi->softDeletions));
2323 -
2324 -
2325 +
2326 +
2327 /* Check chunk bitmap legal */
2328 inUse = yaffs_CountChunkBits(dev,n);
2329 if(inUse != bi->pagesInUse)
2330 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR),
2331 n,bi->pagesInUse,inUse));
2332 -
2333 +
2334 /* Check that the sequence number is valid.
2335 - * Ten million is legal, but is very unlikely
2336 + * Ten million is legal, but is very unlikely
2337 */
2338 - if(dev->isYaffs2 &&
2339 + if(dev->isYaffs2 &&
2340 (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) &&
2341 (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 ))
2342 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR),
2343 n,bi->sequenceNumber));
2344 -
2345 +
2346 }
2347
2348 static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
2349 {
2350 yaffs_VerifyBlock(dev,bi,n);
2351 -
2352 +
2353 /* After collection the block should be in the erased state */
2354 - /* TODO: This will need to change if we do partial gc */
2355 -
2356 - if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
2357 + /* This will need to change if we do partial gc */
2358 +
2359 + if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING &&
2360 + bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
2361 T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR),
2362 n,bi->blockState));
2363 }
2364 @@ -479,28 +492,28 @@ static void yaffs_VerifyBlocks(yaffs_Dev
2365 int i;
2366 int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
2367 int nIllegalBlockStates = 0;
2368 -
2369 +
2370
2371 if(yaffs_SkipVerification(dev))
2372 return;
2373
2374 memset(nBlocksPerState,0,sizeof(nBlocksPerState));
2375
2376 -
2377 +
2378 for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){
2379 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
2380 yaffs_VerifyBlock(dev,bi,i);
2381
2382 - if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
2383 + if(bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
2384 nBlocksPerState[bi->blockState]++;
2385 else
2386 nIllegalBlockStates++;
2387 -
2388 +
2389 }
2390 -
2391 +
2392 T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
2393 T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR)));
2394 -
2395 +
2396 T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates));
2397 if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
2398 T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR)));
2399 @@ -509,17 +522,17 @@ static void yaffs_VerifyBlocks(yaffs_Dev
2400 T(YAFFS_TRACE_VERIFY,
2401 (TSTR("%s %d blocks"TENDSTR),
2402 blockStateName[i],nBlocksPerState[i]));
2403 -
2404 +
2405 if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])
2406 T(YAFFS_TRACE_VERIFY,
2407 (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),
2408 dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]));
2409 -
2410 +
2411 if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])
2412 T(YAFFS_TRACE_VERIFY,
2413 (TSTR("Erased block count wrong dev %d count %d"TENDSTR),
2414 dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]));
2415 -
2416 +
2417 if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)
2418 T(YAFFS_TRACE_VERIFY,
2419 (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),
2420 @@ -535,16 +548,16 @@ static void yaffs_VerifyBlocks(yaffs_Dev
2421 */
2422 static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
2423 {
2424 - if(yaffs_SkipVerification(obj->myDev))
2425 + if(obj && yaffs_SkipVerification(obj->myDev))
2426 return;
2427 -
2428 +
2429 if(!(tags && obj && oh)){
2430 T(YAFFS_TRACE_VERIFY,
2431 (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR),
2432 (__u32)tags,(__u32)obj,(__u32)oh));
2433 return;
2434 }
2435 -
2436 +
2437 if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
2438 oh->type > YAFFS_OBJECT_TYPE_MAX)
2439 T(YAFFS_TRACE_VERIFY,
2440 @@ -559,25 +572,25 @@ static void yaffs_VerifyObjectHeader(yaf
2441
2442 /*
2443 * Check that the object's parent ids match if parentCheck requested.
2444 - *
2445 + *
2446 * Tests do not apply to the root object.
2447 */
2448 -
2449 +
2450 if(parentCheck && tags->objectId > 1 && !obj->parent)
2451 T(YAFFS_TRACE_VERIFY,
2452 (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),
2453 tags->objectId, oh->parentObjectId));
2454 -
2455 -
2456 +
2457 +
2458 if(parentCheck && obj->parent &&
2459 - oh->parentObjectId != obj->parent->objectId &&
2460 + oh->parentObjectId != obj->parent->objectId &&
2461 (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||
2462 obj->parent->objectId != YAFFS_OBJECTID_DELETED))
2463 T(YAFFS_TRACE_VERIFY,
2464 (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),
2465 tags->objectId, oh->parentObjectId, obj->parent->objectId));
2466 -
2467 -
2468 +
2469 +
2470 if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */
2471 T(YAFFS_TRACE_VERIFY,
2472 (TSTR("Obj %d header name is NULL"TENDSTR),
2473 @@ -597,7 +610,6 @@ static int yaffs_VerifyTnodeWorker(yaffs
2474 int i;
2475 yaffs_Device *dev = obj->myDev;
2476 int ok = 1;
2477 - int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2478
2479 if (tn) {
2480 if (level > 0) {
2481 @@ -611,15 +623,14 @@ static int yaffs_VerifyTnodeWorker(yaffs
2482 }
2483 }
2484 } else if (level == 0) {
2485 - int i;
2486 yaffs_ExtendedTags tags;
2487 __u32 objectId = obj->objectId;
2488 -
2489 +
2490 chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS;
2491 -
2492 +
2493 for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
2494 __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2495 -
2496 +
2497 if(theChunk > 0){
2498 /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
2499 yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
2500 @@ -646,18 +657,20 @@ static void yaffs_VerifyFile(yaffs_Objec
2501 __u32 lastChunk;
2502 __u32 x;
2503 __u32 i;
2504 - int ok;
2505 yaffs_Device *dev;
2506 yaffs_ExtendedTags tags;
2507 yaffs_Tnode *tn;
2508 __u32 objectId;
2509 -
2510 - if(obj && yaffs_SkipVerification(obj->myDev))
2511 +
2512 + if(!obj)
2513 return;
2514
2515 + if(yaffs_SkipVerification(obj->myDev))
2516 + return;
2517 +
2518 dev = obj->myDev;
2519 objectId = obj->objectId;
2520 -
2521 +
2522 /* Check file size is consistent with tnode depth */
2523 lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;
2524 x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;
2525 @@ -666,23 +679,23 @@ static void yaffs_VerifyFile(yaffs_Objec
2526 x >>= YAFFS_TNODES_INTERNAL_BITS;
2527 requiredTallness++;
2528 }
2529 -
2530 +
2531 actualTallness = obj->variant.fileVariant.topLevel;
2532 -
2533 +
2534 if(requiredTallness > actualTallness )
2535 T(YAFFS_TRACE_VERIFY,
2536 (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),
2537 obj->objectId,actualTallness, requiredTallness));
2538 -
2539 -
2540 - /* Check that the chunks in the tnode tree are all correct.
2541 +
2542 +
2543 + /* Check that the chunks in the tnode tree are all correct.
2544 * We do this by scanning through the tnode tree and
2545 * checking the tags for every chunk match.
2546 */
2547
2548 if(yaffs_SkipNANDVerification(dev))
2549 return;
2550 -
2551 +
2552 for(i = 1; i <= lastChunk; i++){
2553 tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i);
2554
2555 @@ -703,18 +716,12 @@ static void yaffs_VerifyFile(yaffs_Objec
2556
2557 }
2558
2559 -static void yaffs_VerifyDirectory(yaffs_Object *obj)
2560 -{
2561 - if(obj && yaffs_SkipVerification(obj->myDev))
2562 - return;
2563 -
2564 -}
2565
2566 static void yaffs_VerifyHardLink(yaffs_Object *obj)
2567 {
2568 if(obj && yaffs_SkipVerification(obj->myDev))
2569 return;
2570 -
2571 +
2572 /* Verify sane equivalent object */
2573 }
2574
2575 @@ -722,7 +729,7 @@ static void yaffs_VerifySymlink(yaffs_Ob
2576 {
2577 if(obj && yaffs_SkipVerification(obj->myDev))
2578 return;
2579 -
2580 +
2581 /* Verify symlink string */
2582 }
2583
2584 @@ -735,69 +742,77 @@ static void yaffs_VerifySpecial(yaffs_Ob
2585 static void yaffs_VerifyObject(yaffs_Object *obj)
2586 {
2587 yaffs_Device *dev;
2588 -
2589 +
2590 __u32 chunkMin;
2591 __u32 chunkMax;
2592 -
2593 +
2594 __u32 chunkIdOk;
2595 - __u32 chunkIsLive;
2596 -
2597 + __u32 chunkInRange;
2598 + __u32 chunkShouldNotBeDeleted;
2599 + __u32 chunkValid;
2600 +
2601 if(!obj)
2602 return;
2603 -
2604 +
2605 + if(obj->beingCreated)
2606 + return;
2607 +
2608 dev = obj->myDev;
2609 -
2610 +
2611 if(yaffs_SkipVerification(dev))
2612 return;
2613 -
2614 +
2615 /* Check sane object header chunk */
2616
2617 chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
2618 chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
2619
2620 - chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax);
2621 - chunkIsLive = chunkIdOk &&
2622 + chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
2623 + chunkIdOk = chunkInRange || obj->hdrChunk == 0;
2624 + chunkValid = chunkInRange &&
2625 yaffs_CheckChunkBit(dev,
2626 - obj->chunkId / dev->nChunksPerBlock,
2627 - obj->chunkId % dev->nChunksPerBlock);
2628 + obj->hdrChunk / dev->nChunksPerBlock,
2629 + obj->hdrChunk % dev->nChunksPerBlock);
2630 + chunkShouldNotBeDeleted = chunkInRange && !chunkValid;
2631 +
2632 if(!obj->fake &&
2633 - (!chunkIdOk || !chunkIsLive)) {
2634 + (!chunkIdOk || chunkShouldNotBeDeleted)) {
2635 T(YAFFS_TRACE_VERIFY,
2636 (TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
2637 - obj->objectId,obj->chunkId,
2638 + obj->objectId,obj->hdrChunk,
2639 chunkIdOk ? "" : ",out of range",
2640 - chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
2641 + chunkShouldNotBeDeleted ? ",marked as deleted" : ""));
2642 }
2643 -
2644 - if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
2645 +
2646 + if(chunkValid &&!yaffs_SkipNANDVerification(dev)) {
2647 yaffs_ExtendedTags tags;
2648 yaffs_ObjectHeader *oh;
2649 __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
2650 -
2651 +
2652 oh = (yaffs_ObjectHeader *)buffer;
2653
2654 - yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
2655 + yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags);
2656
2657 yaffs_VerifyObjectHeader(obj,oh,&tags,1);
2658 -
2659 +
2660 yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
2661 }
2662 -
2663 +
2664 /* Verify it has a parent */
2665 if(obj && !obj->fake &&
2666 (!obj->parent || obj->parent->myDev != dev)){
2667 T(YAFFS_TRACE_VERIFY,
2668 (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),
2669 - obj->objectId,obj->parent));
2670 + obj->objectId,obj->parent));
2671 }
2672 -
2673 +
2674 /* Verify parent is a directory */
2675 if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
2676 T(YAFFS_TRACE_VERIFY,
2677 (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),
2678 - obj->objectId,obj->parent->variantType));
2679 + obj->objectId,obj->parent->variantType));
2680 }
2681 -
2682 +
2683 switch(obj->variantType){
2684 case YAFFS_OBJECT_TYPE_FILE:
2685 yaffs_VerifyFile(obj);
2686 @@ -818,31 +833,31 @@ static void yaffs_VerifyObject(yaffs_Obj
2687 default:
2688 T(YAFFS_TRACE_VERIFY,
2689 (TSTR("Obj %d has illegaltype %d"TENDSTR),
2690 - obj->objectId,obj->variantType));
2691 + obj->objectId,obj->variantType));
2692 break;
2693 }
2694 -
2695 -
2696 +
2697 +
2698 }
2699
2700 static void yaffs_VerifyObjects(yaffs_Device *dev)
2701 {
2702 - yaffs_Object *obj;
2703 - int i;
2704 - struct list_head *lh;
2705 -
2706 - if(yaffs_SkipVerification(dev))
2707 - return;
2708 -
2709 - /* Iterate through the objects in each hash entry */
2710 -
2711 - for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
2712 - list_for_each(lh, &dev->objectBucket[i].list) {
2713 - if (lh) {
2714 - obj = list_entry(lh, yaffs_Object, hashLink);
2715 - yaffs_VerifyObject(obj);
2716 - }
2717 - }
2718 + yaffs_Object *obj;
2719 + int i;
2720 + struct ylist_head *lh;
2721 +
2722 + if(yaffs_SkipVerification(dev))
2723 + return;
2724 +
2725 + /* Iterate through the objects in each hash entry */
2726 +
2727 + for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
2728 + ylist_for_each(lh, &dev->objectBucket[i].list) {
2729 + if (lh) {
2730 + obj = ylist_entry(lh, yaffs_Object, hashLink);
2731 + yaffs_VerifyObject(obj);
2732 + }
2733 + }
2734 }
2735
2736 }
2737 @@ -851,7 +866,7 @@ static void yaffs_VerifyObjects(yaffs_De
2738 /*
2739 * Simple hash function. Needs to have a reasonable spread
2740 */
2741 -
2742 +
2743 static Y_INLINE int yaffs_HashFunction(int n)
2744 {
2745 n = abs(n);
2746 @@ -859,9 +874,10 @@ static Y_INLINE int yaffs_HashFunction(i
2747 }
2748
2749 /*
2750 - * Access functions to useful fake objects
2751 + * Access functions to useful fake objects.
2752 + * Note that root might have a presence in NAND if permissions are set.
2753 */
2754 -
2755 +
2756 yaffs_Object *yaffs_Root(yaffs_Device * dev)
2757 {
2758 return dev->rootDir;
2759 @@ -876,7 +892,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Dev
2760 /*
2761 * Erased NAND checking functions
2762 */
2763 -
2764 +
2765 int yaffs_CheckFF(__u8 * buffer, int nBytes)
2766 {
2767 /* Horrible, slow implementation */
2768 @@ -898,10 +914,10 @@ static int yaffs_CheckChunkErased(struct
2769 int result;
2770
2771 result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
2772 -
2773 +
2774 if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
2775 retval = YAFFS_FAIL;
2776 -
2777 +
2778
2779 if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
2780 T(YAFFS_TRACE_NANDACCESS,
2781 @@ -915,7 +931,6 @@ static int yaffs_CheckChunkErased(struct
2782
2783 }
2784
2785 -
2786 static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
2787 const __u8 * data,
2788 yaffs_ExtendedTags * tags,
2789 @@ -992,7 +1007,11 @@ static int yaffs_WriteNewChunkWithTagsTo
2790 /* Copy the data into the robustification buffer */
2791 yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
2792
2793 - } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts);
2794 + } while (writeOk != YAFFS_OK &&
2795 + (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
2796 +
2797 + if(!writeOk)
2798 + chunk = -1;
2799
2800 if (attempts > 1) {
2801 T(YAFFS_TRACE_ERROR,
2802 @@ -1008,13 +1027,13 @@ static int yaffs_WriteNewChunkWithTagsTo
2803 /*
2804 * Block retiring for handling a broken block.
2805 */
2806 -
2807 +
2808 static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
2809 {
2810 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2811
2812 yaffs_InvalidateCheckpoint(dev);
2813 -
2814 +
2815 yaffs_MarkBlockBad(dev, blockInNAND);
2816
2817 bi->blockState = YAFFS_BLOCK_STATE_DEAD;
2818 @@ -1028,7 +1047,7 @@ static void yaffs_RetireBlock(yaffs_Devi
2819 * Functions for robustisizing TODO
2820 *
2821 */
2822 -
2823 +
2824 static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
2825 const __u8 * data,
2826 const yaffs_ExtendedTags * tags)
2827 @@ -1046,13 +1065,13 @@ void yaffs_HandleChunkError(yaffs_Device
2828 bi->gcPrioritise = 1;
2829 dev->hasPendingPrioritisedGCs = 1;
2830 bi->chunkErrorStrikes ++;
2831 -
2832 +
2833 if(bi->chunkErrorStrikes > 3){
2834 bi->needsRetiring = 1; /* Too many stikes, so retire this */
2835 T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
2836
2837 }
2838 -
2839 +
2840 }
2841 }
2842
2843 @@ -1063,30 +1082,30 @@ static void yaffs_HandleWriteChunkError(
2844 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2845
2846 yaffs_HandleChunkError(dev,bi);
2847 -
2848 -
2849 +
2850 +
2851 if(erasedOk ) {
2852 /* Was an actual write failure, so mark the block for retirement */
2853 bi->needsRetiring = 1;
2854 T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
2855 (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
2856
2857 -
2858 +
2859 }
2860 -
2861 +
2862 /* Delete the chunk */
2863 yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
2864 }
2865
2866
2867 -/*---------------- Name handling functions ------------*/
2868 +/*---------------- Name handling functions ------------*/
2869
2870 static __u16 yaffs_CalcNameSum(const YCHAR * name)
2871 {
2872 __u16 sum = 0;
2873 __u16 i = 1;
2874
2875 - YUCHAR *bname = (YUCHAR *) name;
2876 + const YUCHAR *bname = (const YUCHAR *) name;
2877 if (bname) {
2878 while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
2879
2880 @@ -1099,12 +1118,14 @@ static __u16 yaffs_CalcNameSum(const YCH
2881 bname++;
2882 }
2883 }
2884 +
2885 return sum;
2886 }
2887
2888 static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
2889 {
2890 #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
2891 + memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1));
2892 if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
2893 yaffs_strcpy(obj->shortName, name);
2894 } else {
2895 @@ -1120,7 +1141,7 @@ static void yaffs_SetObjectName(yaffs_Ob
2896 * The list is hooked together using the first pointer
2897 * in the tnode.
2898 */
2899 -
2900 +
2901 /* yaffs_CreateTnodes creates a bunch more tnodes and
2902 * adds them to the tnode free list.
2903 * Don't use this function directly
2904 @@ -1138,11 +1159,15 @@ static int yaffs_CreateTnodes(yaffs_Devi
2905
2906 if (nTnodes < 1)
2907 return YAFFS_OK;
2908 -
2909 +
2910 /* Calculate the tnode size in bytes for variable width tnode support.
2911 * Must be a multiple of 32-bits */
2912 tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2913
2914 + if(tnodeSize < sizeof(yaffs_Tnode))
2915 + tnodeSize = sizeof(yaffs_Tnode);
2916 +
2917 +
2918 /* make these things */
2919
2920 newTnodes = YMALLOC(nTnodes * tnodeSize);
2921 @@ -1175,7 +1200,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
2922 next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
2923 curr->internal[0] = next;
2924 }
2925 -
2926 +
2927 curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
2928 curr->internal[0] = dev->freeTnodes;
2929 dev->freeTnodes = (yaffs_Tnode *)mem;
2930 @@ -1190,7 +1215,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
2931 * NB If we can't add this to the management list it isn't fatal
2932 * but it just means we can't free this bunch of tnodes later.
2933 */
2934 -
2935 +
2936 tnl = YMALLOC(sizeof(yaffs_TnodeList));
2937 if (!tnl) {
2938 T(YAFFS_TRACE_ERROR,
2939 @@ -1233,17 +1258,23 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya
2940 dev->nFreeTnodes--;
2941 }
2942
2943 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2944 +
2945 return tn;
2946 }
2947
2948 static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
2949 {
2950 yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
2951 + int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2952
2953 + if(tnodeSize < sizeof(yaffs_Tnode))
2954 + tnodeSize = sizeof(yaffs_Tnode);
2955 +
2956 if(tn)
2957 - memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
2958 + memset(tn, 0, tnodeSize);
2959
2960 - return tn;
2961 + return tn;
2962 }
2963
2964 /* FreeTnode frees up a tnode and puts it back on the free list */
2965 @@ -1262,6 +1293,8 @@ static void yaffs_FreeTnode(yaffs_Device
2966 dev->freeTnodes = tn;
2967 dev->nFreeTnodes++;
2968 }
2969 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2970 +
2971 }
2972
2973 static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
2974 @@ -1299,19 +1332,19 @@ void yaffs_PutLevel0Tnode(yaffs_Device *
2975 __u32 bitInWord;
2976 __u32 wordInMap;
2977 __u32 mask;
2978 -
2979 +
2980 pos &= YAFFS_TNODES_LEVEL0_MASK;
2981 val >>= dev->chunkGroupBits;
2982 -
2983 +
2984 bitInMap = pos * dev->tnodeWidth;
2985 wordInMap = bitInMap /32;
2986 bitInWord = bitInMap & (32 -1);
2987 -
2988 +
2989 mask = dev->tnodeMask << bitInWord;
2990 -
2991 +
2992 map[wordInMap] &= ~mask;
2993 map[wordInMap] |= (mask & (val << bitInWord));
2994 -
2995 +
2996 if(dev->tnodeWidth > (32-bitInWord)) {
2997 bitInWord = (32 - bitInWord);
2998 wordInMap++;;
2999 @@ -1328,24 +1361,24 @@ static __u32 yaffs_GetChunkGroupBase(yaf
3000 __u32 bitInWord;
3001 __u32 wordInMap;
3002 __u32 val;
3003 -
3004 +
3005 pos &= YAFFS_TNODES_LEVEL0_MASK;
3006 -
3007 +
3008 bitInMap = pos * dev->tnodeWidth;
3009 wordInMap = bitInMap /32;
3010 bitInWord = bitInMap & (32 -1);
3011 -
3012 +
3013 val = map[wordInMap] >> bitInWord;
3014 -
3015 +
3016 if(dev->tnodeWidth > (32-bitInWord)) {
3017 bitInWord = (32 - bitInWord);
3018 wordInMap++;;
3019 val |= (map[wordInMap] << bitInWord);
3020 }
3021 -
3022 +
3023 val &= dev->tnodeMask;
3024 val <<= dev->chunkGroupBits;
3025 -
3026 +
3027 return val;
3028 }
3029
3030 @@ -1394,7 +1427,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
3031 while (level > 0 && tn) {
3032 tn = tn->
3033 internal[(chunkId >>
3034 - ( YAFFS_TNODES_LEVEL0_BITS +
3035 + ( YAFFS_TNODES_LEVEL0_BITS +
3036 (level - 1) *
3037 YAFFS_TNODES_INTERNAL_BITS)
3038 ) &
3039 @@ -1416,7 +1449,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
3040 * If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
3041 * be plugged into the ttree.
3042 */
3043 -
3044 +
3045 static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
3046 yaffs_FileStructure * fStruct,
3047 __u32 chunkId,
3048 @@ -1453,7 +1486,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
3049 if (requiredTallness > fStruct->topLevel) {
3050 /* Not tall enough,gotta make the tree taller */
3051 for (i = fStruct->topLevel; i < requiredTallness; i++) {
3052 -
3053 +
3054 tn = yaffs_GetTnode(dev);
3055
3056 if (tn) {
3057 @@ -1472,7 +1505,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
3058
3059 l = fStruct->topLevel;
3060 tn = fStruct->top;
3061 -
3062 +
3063 if(l > 0) {
3064 while (l > 0 && tn) {
3065 x = (chunkId >>
3066 @@ -1492,13 +1525,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
3067 if(tn->internal[x])
3068 yaffs_FreeTnode(dev,tn->internal[x]);
3069 tn->internal[x] = passedTn;
3070 -
3071 +
3072 } else if(!tn->internal[x]) {
3073 /* Don't have one, none passed in */
3074 tn->internal[x] = yaffs_GetTnode(dev);
3075 }
3076 }
3077 -
3078 +
3079 tn = tn->internal[x];
3080 l--;
3081 }
3082 @@ -1539,7 +1572,7 @@ static int yaffs_FindChunkInGroup(yaffs_
3083
3084 /* DeleteWorker scans backwards through the tnode tree and deletes all the
3085 * chunks and tnodes in the file
3086 - * Returns 1 if the tree was deleted.
3087 + * Returns 1 if the tree was deleted.
3088 * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
3089 */
3090
3091 @@ -1653,7 +1686,7 @@ static void yaffs_SoftDeleteChunk(yaffs_
3092 * of the tnode.
3093 * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
3094 */
3095 -
3096 +
3097 static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
3098 __u32 level, int chunkOffset)
3099 {
3100 @@ -1694,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_
3101 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
3102 if (theChunk) {
3103 /* Note this does not find the real chunk, only the chunk group.
3104 - * We make an assumption that a chunk group is not larger than
3105 + * We make an assumption that a chunk group is not larger than
3106 * a block.
3107 */
3108 yaffs_SoftDeleteChunk(dev, theChunk);
3109 @@ -1796,7 +1829,7 @@ static int yaffs_PruneFileStructure(yaff
3110 /* Now we have a tree with all the non-zero branches NULL but the height
3111 * is the same as it was.
3112 * Let's see if we can trim internal tnodes to shorten the tree.
3113 - * We can do this if only the 0th element in the tnode is in use
3114 + * We can do this if only the 0th element in the tnode is in use
3115 * (ie all the non-zero are NULL)
3116 */
3117
3118 @@ -1850,14 +1883,14 @@ static int yaffs_CreateFreeObjects(yaffs
3119 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
3120 return YAFFS_FAIL;
3121 }
3122 +
3123 + /* Hook them into the free list */
3124 + for (i = 0; i < nObjects - 1; i++) {
3125 + newObjects[i].siblings.next =
3126 + (struct ylist_head *)(&newObjects[i + 1]);
3127 + }
3128
3129 - /* Hook them into the free list */
3130 - for (i = 0; i < nObjects - 1; i++) {
3131 - newObjects[i].siblings.next =
3132 - (struct list_head *)(&newObjects[i + 1]);
3133 - }
3134 -
3135 - newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
3136 + newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
3137 dev->freeObjects = newObjects;
3138 dev->nFreeObjects += nObjects;
3139 dev->nObjectsCreated += nObjects;
3140 @@ -1877,6 +1910,9 @@ static yaffs_Object *yaffs_AllocateEmpty
3141 {
3142 yaffs_Object *tn = NULL;
3143
3144 +#ifdef VALGRIND_TEST
3145 + tn = YMALLOC(sizeof(yaffs_Object));
3146 +#else
3147 /* If there are none left make more */
3148 if (!dev->freeObjects) {
3149 yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
3150 @@ -1887,25 +1923,40 @@ static yaffs_Object *yaffs_AllocateEmpty
3151 dev->freeObjects =
3152 (yaffs_Object *) (dev->freeObjects->siblings.next);
3153 dev->nFreeObjects--;
3154 -
3155 + }
3156 +#endif
3157 + if(tn){
3158 /* Now sweeten it up... */
3159
3160 memset(tn, 0, sizeof(yaffs_Object));
3161 + tn->beingCreated = 1;
3162 +
3163 tn->myDev = dev;
3164 - tn->chunkId = -1;
3165 + tn->hdrChunk = 0;
3166 tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
3167 - INIT_LIST_HEAD(&(tn->hardLinks));
3168 - INIT_LIST_HEAD(&(tn->hashLink));
3169 - INIT_LIST_HEAD(&tn->siblings);
3170 + YINIT_LIST_HEAD(&(tn->hardLinks));
3171 + YINIT_LIST_HEAD(&(tn->hashLink));
3172 + YINIT_LIST_HEAD(&tn->siblings);
3173 +
3174 +
3175 + /* Now make the directory sane */
3176 + if(dev->rootDir){
3177 + tn->parent = dev->rootDir;
3178 + ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children);
3179 + }
3180
3181 - /* Add it to the lost and found directory.
3182 - * NB Can't put root or lostNFound in lostNFound so
3183 + /* Add it to the lost and found directory.
3184 + * NB Can't put root or lostNFound in lostNFound so
3185 * check if lostNFound exists first
3186 */
3187 if (dev->lostNFoundDir) {
3188 yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
3189 }
3190 +
3191 + tn->beingCreated = 0;
3192 }
3193 +
3194 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
3195
3196 return tn;
3197 }
3198 @@ -1917,14 +1968,14 @@ static yaffs_Object *yaffs_CreateFakeDir
3199 yaffs_Object *obj =
3200 yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
3201 if (obj) {
3202 - obj->fake = 1; /* it is fake so it has no NAND presence... */
3203 + obj->fake = 1; /* it is fake so it might have no NAND presence... */
3204 obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
3205 obj->unlinkAllowed = 0; /* ... or unlink it */
3206 obj->deleted = 0;
3207 obj->unlinked = 0;
3208 obj->yst_mode = mode;
3209 obj->myDev = dev;
3210 - obj->chunkId = 0; /* Not a valid chunk. */
3211 + obj->hdrChunk = 0; /* Not a valid chunk. */
3212 }
3213
3214 return obj;
3215 @@ -1934,14 +1985,14 @@ static yaffs_Object *yaffs_CreateFakeDir
3216 static void yaffs_UnhashObject(yaffs_Object * tn)
3217 {
3218 int bucket;
3219 - yaffs_Device *dev = tn->myDev;
3220 + yaffs_Device *dev = tn->myDev;
3221
3222 - /* If it is still linked into the bucket list, free from the list */
3223 - if (!list_empty(&tn->hashLink)) {
3224 - list_del_init(&tn->hashLink);
3225 - bucket = yaffs_HashFunction(tn->objectId);
3226 - dev->objectBucket[bucket].count--;
3227 - }
3228 + /* If it is still linked into the bucket list, free from the list */
3229 + if (!ylist_empty(&tn->hashLink)) {
3230 + ylist_del_init(&tn->hashLink);
3231 + bucket = yaffs_HashFunction(tn->objectId);
3232 + dev->objectBucket[bucket].count--;
3233 + }
3234
3235 }
3236
3237 @@ -1951,6 +2002,13 @@ static void yaffs_FreeObject(yaffs_Objec
3238
3239 yaffs_Device *dev = tn->myDev;
3240
3241 +
3242 + if(tn->parent)
3243 + YBUG();
3244 + if(!ylist_empty(&tn->siblings))
3245 + YBUG();
3246 +
3247 +
3248 #ifdef __KERNEL__
3249 if (tn->myInode) {
3250 /* We're still hooked up to a cached inode.
3251 @@ -1961,12 +2019,18 @@ static void yaffs_FreeObject(yaffs_Objec
3252 }
3253 #endif
3254
3255 - yaffs_UnhashObject(tn);
3256 + yaffs_UnhashObject(tn);
3257 +
3258 +#ifdef VALGRIND_TEST
3259 + YFREE(tn);
3260 +#else
3261 + /* Link into the free list. */
3262 + tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
3263 + dev->freeObjects = tn;
3264 + dev->nFreeObjects++;
3265 +#endif
3266 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
3267
3268 - /* Link into the free list. */
3269 - tn->siblings.next = (struct list_head *)(dev->freeObjects);
3270 - dev->freeObjects = tn;
3271 - dev->nFreeObjects++;
3272 }
3273
3274 #ifdef __KERNEL__
3275 @@ -2004,12 +2068,12 @@ static void yaffs_InitialiseObjects(yaff
3276
3277 dev->allocatedObjectList = NULL;
3278 dev->freeObjects = NULL;
3279 - dev->nFreeObjects = 0;
3280 + dev->nFreeObjects = 0;
3281
3282 - for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
3283 - INIT_LIST_HEAD(&dev->objectBucket[i].list);
3284 - dev->objectBucket[i].count = 0;
3285 - }
3286 + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
3287 + YINIT_LIST_HEAD(&dev->objectBucket[i].list);
3288 + dev->objectBucket[i].count = 0;
3289 + }
3290
3291 }
3292
3293 @@ -2055,26 +2119,26 @@ static int yaffs_CreateNewObjectNumber(y
3294
3295 /* Now find an object value that has not already been taken
3296 * by scanning the list.
3297 - */
3298 + */
3299
3300 - int found = 0;
3301 - struct list_head *i;
3302 + int found = 0;
3303 + struct ylist_head *i;
3304
3305 - __u32 n = (__u32) bucket;
3306 + __u32 n = (__u32) bucket;
3307
3308 /* yaffs_CheckObjectHashSanity(); */
3309
3310 while (!found) {
3311 - found = 1;
3312 - n += YAFFS_NOBJECT_BUCKETS;
3313 - if (1 || dev->objectBucket[bucket].count > 0) {
3314 - list_for_each(i, &dev->objectBucket[bucket].list) {
3315 - /* If there is already one in the list */
3316 - if (i
3317 - && list_entry(i, yaffs_Object,
3318 - hashLink)->objectId == n) {
3319 - found = 0;
3320 - }
3321 + found = 1;
3322 + n += YAFFS_NOBJECT_BUCKETS;
3323 + if (1 || dev->objectBucket[bucket].count > 0) {
3324 + ylist_for_each(i, &dev->objectBucket[bucket].list) {
3325 + /* If there is already one in the list */
3326 + if (i
3327 + && ylist_entry(i, yaffs_Object,
3328 + hashLink)->objectId == n) {
3329 + found = 0;
3330 + }
3331 }
3332 }
3333 }
3334 @@ -2085,27 +2149,27 @@ static int yaffs_CreateNewObjectNumber(y
3335
3336 static void yaffs_HashObject(yaffs_Object * in)
3337 {
3338 - int bucket = yaffs_HashFunction(in->objectId);
3339 - yaffs_Device *dev = in->myDev;
3340 + int bucket = yaffs_HashFunction(in->objectId);
3341 + yaffs_Device *dev = in->myDev;
3342
3343 - list_add(&in->hashLink, &dev->objectBucket[bucket].list);
3344 - dev->objectBucket[bucket].count++;
3345 + ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
3346 + dev->objectBucket[bucket].count++;
3347
3348 }
3349
3350 yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
3351 {