[kernel] generic-2.6/2.6.28: sync yaffs code with the current CVS version
[openwrt.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  {
3352 -       int bucket = yaffs_HashFunction(number);
3353 -       struct list_head *i;
3354 -       yaffs_Object *in;
3355 -
3356 -       list_for_each(i, &dev->objectBucket[bucket].list) {
3357 -               /* Look if it is in the list */
3358 -               if (i) {
3359 -                       in = list_entry(i, yaffs_Object, hashLink);
3360 -                       if (in->objectId == number) {
3361 +        int bucket = yaffs_HashFunction(number);
3362 +        struct ylist_head *i;
3363 +        yaffs_Object *in;
3364 +
3365 +        ylist_for_each(i, &dev->objectBucket[bucket].list) {
3366 +                /* Look if it is in the list */
3367 +                if (i) {
3368 +                        in = ylist_entry(i, yaffs_Object, hashLink);
3369 +                        if (in->objectId == number) {
3370  #ifdef __KERNEL__
3371 -                               /* Don't tell the VFS about this one if it is defered free */
3372 +                                /* Don't tell the VFS about this one if it is defered free */
3373                                 if (in->deferedFree)
3374                                         return NULL;
3375  #endif
3376 @@ -2123,7 +2187,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
3377  {
3378  
3379         yaffs_Object *theObject;
3380 -       yaffs_Tnode *tn;
3381 +       yaffs_Tnode *tn = NULL;
3382  
3383         if (number < 0) {
3384                 number = yaffs_CreateNewObjectNumber(dev);
3385 @@ -2132,7 +2196,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
3386         theObject = yaffs_AllocateEmptyObject(dev);
3387         if(!theObject)
3388                 return NULL;
3389 -
3390 +               
3391         if(type == YAFFS_OBJECT_TYPE_FILE){
3392                 tn = yaffs_GetTnode(dev);
3393                 if(!tn){
3394 @@ -2140,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaff
3395                         return NULL;
3396                 }
3397         }
3398 -
3399 -
3400 +               
3401 +       
3402  
3403         if (theObject) {
3404                 theObject->fake = 0;
3405 @@ -2162,19 +2226,25 @@ yaffs_Object *yaffs_CreateNewObject(yaff
3406                 theObject->yst_atime = theObject->yst_mtime =
3407                     theObject->yst_ctime = Y_CURRENT_TIME;
3408  #endif
3409 +
3410 +#if 0
3411 +               theObject->sum_prev = 12345;
3412 +               theObject->sum_trailer = 6789;
3413 +#endif
3414 +
3415                 switch (type) {
3416                 case YAFFS_OBJECT_TYPE_FILE:
3417                         theObject->variant.fileVariant.fileSize = 0;
3418                         theObject->variant.fileVariant.scannedFileSize = 0;
3419                         theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */
3420                         theObject->variant.fileVariant.topLevel = 0;
3421 -                       theObject->variant.fileVariant.top = tn;
3422 -                       break;
3423 -               case YAFFS_OBJECT_TYPE_DIRECTORY:
3424 -                       INIT_LIST_HEAD(&theObject->variant.directoryVariant.
3425 -                                      children);
3426 -                       break;
3427 -               case YAFFS_OBJECT_TYPE_SYMLINK:
3428 +                        theObject->variant.fileVariant.top = tn;
3429 +                        break;
3430 +                case YAFFS_OBJECT_TYPE_DIRECTORY:
3431 +                        YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
3432 +                                       children);
3433 +                        break;
3434 +                case YAFFS_OBJECT_TYPE_SYMLINK:
3435                 case YAFFS_OBJECT_TYPE_HARDLINK:
3436                 case YAFFS_OBJECT_TYPE_SPECIAL:
3437                         /* No action required */
3438 @@ -2205,7 +2275,7 @@ static yaffs_Object *yaffs_FindOrCreateO
3439         return theObject;
3440  
3441  }
3442 -
3443 +                       
3444  
3445  static YCHAR *yaffs_CloneString(const YCHAR * str)
3446  {
3447 @@ -2227,7 +2297,7 @@ static YCHAR *yaffs_CloneString(const YC
3448   * aliasString only has meaning for a sumlink.
3449   * rdev only has meaning for devices (a subset of special objects)
3450   */
3451 -
3452
3453  static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
3454                                        yaffs_Object * parent,
3455                                        const YCHAR * name,
3456 @@ -2238,7 +2308,7 @@ static yaffs_Object *yaffs_MknodObject(y
3457                                        const YCHAR * aliasString, __u32 rdev)
3458  {
3459         yaffs_Object *in;
3460 -       YCHAR *str;
3461 +       YCHAR *str = NULL;
3462  
3463         yaffs_Device *dev = parent->myDev;
3464  
3465 @@ -2249,6 +2319,9 @@ static yaffs_Object *yaffs_MknodObject(y
3466  
3467         in = yaffs_CreateNewObject(dev, -1, type);
3468  
3469 +       if(!in)
3470 +               return YAFFS_FAIL;
3471 +       
3472         if(type == YAFFS_OBJECT_TYPE_SYMLINK){
3473                 str = yaffs_CloneString(aliasString);
3474                 if(!str){
3475 @@ -2256,11 +2329,11 @@ static yaffs_Object *yaffs_MknodObject(y
3476                         return NULL;
3477                 }
3478         }
3479 -
3480 -
3481 +       
3482 +       
3483  
3484         if (in) {
3485 -               in->chunkId = -1;
3486 +               in->hdrChunk = 0;
3487                 in->valid = 1;
3488                 in->variantType = type;
3489  
3490 @@ -2293,13 +2366,13 @@ static yaffs_Object *yaffs_MknodObject(y
3491                         break;
3492                 case YAFFS_OBJECT_TYPE_HARDLINK:
3493                         in->variant.hardLinkVariant.equivalentObject =
3494 -                           equivalentObject;
3495 -                       in->variant.hardLinkVariant.equivalentObjectId =
3496 -                           equivalentObject->objectId;
3497 -                       list_add(&in->hardLinks, &equivalentObject->hardLinks);
3498 -                       break;
3499 -               case YAFFS_OBJECT_TYPE_FILE:
3500 -               case YAFFS_OBJECT_TYPE_DIRECTORY:
3501 +                            equivalentObject;
3502 +                        in->variant.hardLinkVariant.equivalentObjectId =
3503 +                            equivalentObject->objectId;
3504 +                        ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
3505 +                        break;
3506 +                case YAFFS_OBJECT_TYPE_FILE:    
3507 +                case YAFFS_OBJECT_TYPE_DIRECTORY:
3508                 case YAFFS_OBJECT_TYPE_SPECIAL:
3509                 case YAFFS_OBJECT_TYPE_UNKNOWN:
3510                         /* do nothing */
3511 @@ -2378,11 +2451,11 @@ static int yaffs_ChangeObjectName(yaffs_
3512         if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
3513                 T(YAFFS_TRACE_ALWAYS,
3514                   (TSTR
3515 -                  ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
3516 +                  ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"
3517                     TENDSTR)));
3518                 YBUG();
3519         }
3520 -
3521 +       
3522         /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
3523         if (obj->myDev->isYaffs2) {
3524                 unlinkOp = (newDir == obj->myDev->unlinkedDir);
3525 @@ -2395,9 +2468,9 @@ static int yaffs_ChangeObjectName(yaffs_
3526  
3527         existingTarget = yaffs_FindObjectByName(newDir, newName);
3528  
3529 -       /* If the object is a file going into the unlinked directory,
3530 +       /* If the object is a file going into the unlinked directory, 
3531          *   then it is OK to just stuff it in since duplicate names are allowed.
3532 -        *   else only proceed if the new name does not exist and if we're putting
3533 +        *   else only proceed if the new name does not exist and if we're putting 
3534          *   it into a directory.
3535          */
3536         if ((unlinkOp ||
3537 @@ -2425,9 +2498,15 @@ static int yaffs_ChangeObjectName(yaffs_
3538  int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
3539                        yaffs_Object * newDir, const YCHAR * newName)
3540  {
3541 -       yaffs_Object *obj;
3542 -       yaffs_Object *existingTarget;
3543 +       yaffs_Object *obj=NULL;
3544 +       yaffs_Object *existingTarget=NULL;
3545         int force = 0;
3546 +       
3547 +       
3548 +       if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3549 +               YBUG();
3550 +       if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3551 +               YBUG();
3552  
3553  #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
3554         /* Special case for case insemsitive systems (eg. WinCE).
3555 @@ -2439,29 +2518,24 @@ int yaffs_RenameObject(yaffs_Object * ol
3556         }
3557  #endif
3558  
3559 -       obj = yaffs_FindObjectByName(oldDir, oldName);
3560 -       /* Check new name to long. */
3561 -       if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
3562 -           yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
3563 -         /* ENAMETOOLONG */
3564 -         return YAFFS_FAIL;
3565 -       else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
3566 -                yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
3567 +       else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
3568           /* ENAMETOOLONG */
3569           return YAFFS_FAIL;
3570  
3571 +       obj = yaffs_FindObjectByName(oldDir, oldName);
3572 +
3573         if (obj && obj->renameAllowed) {
3574  
3575                 /* Now do the handling for an existing target, if there is one */
3576  
3577 -               existingTarget = yaffs_FindObjectByName(newDir, newName);
3578 -               if (existingTarget &&
3579 -                   existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
3580 -                   !list_empty(&existingTarget->variant.directoryVariant.children)) {
3581 -                       /* There is a target that is a non-empty directory, so we fail */
3582 -                       return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
3583 -               } else if (existingTarget && existingTarget != obj) {
3584 -                       /* Nuke the target first, using shadowing,
3585 +                existingTarget = yaffs_FindObjectByName(newDir, newName);
3586 +                if (existingTarget &&
3587 +                    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
3588 +                    !ylist_empty(&existingTarget->variant.directoryVariant.children)) {
3589 +                        /* There is a target that is a non-empty directory, so we fail */
3590 +                        return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
3591 +                } else if (existingTarget && existingTarget != obj) {
3592 +                       /* Nuke the target first, using shadowing, 
3593                          * but only if it isn't the same object
3594                          */
3595                         yaffs_ChangeObjectName(obj, newDir, newName, force,
3596 @@ -2479,10 +2553,10 @@ int yaffs_RenameObject(yaffs_Object * ol
3597  static int yaffs_InitialiseBlocks(yaffs_Device * dev)
3598  {
3599         int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
3600 -
3601 +       
3602         dev->blockInfo = NULL;
3603         dev->chunkBits = NULL;
3604 -
3605 +       
3606         dev->allocationBlock = -1;      /* force it to get a new one */
3607  
3608         /* If the first allocation strategy fails, thry the alternate one */
3609 @@ -2493,9 +2567,9 @@ static int yaffs_InitialiseBlocks(yaffs_
3610         }
3611         else
3612                 dev->blockInfoAlt = 0;
3613 -
3614 +               
3615         if(dev->blockInfo){
3616 -
3617 +       
3618                 /* Set up dynamic blockinfo stuff. */
3619                 dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
3620                 dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
3621 @@ -2506,7 +2580,7 @@ static int yaffs_InitialiseBlocks(yaffs_
3622                 else
3623                         dev->chunkBitsAlt = 0;
3624         }
3625 -
3626 +       
3627         if (dev->blockInfo && dev->chunkBits) {
3628                 memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
3629                 memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
3630 @@ -2527,7 +2601,7 @@ static void yaffs_DeinitialiseBlocks(yaf
3631         dev->blockInfoAlt = 0;
3632  
3633         dev->blockInfo = NULL;
3634 -
3635 +       
3636         if(dev->chunkBitsAlt && dev->chunkBits)
3637                 YFREE_ALT(dev->chunkBits);
3638         else if(dev->chunkBits)
3639 @@ -2591,14 +2665,14 @@ static int yaffs_FindBlockForGarbageColl
3640         int prioritised=0;
3641         yaffs_BlockInfo *bi;
3642         int pendingPrioritisedExist = 0;
3643 -
3644 +       
3645         /* First let's see if we need to grab a prioritised block */
3646         if(dev->hasPendingPrioritisedGCs){
3647                 for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
3648  
3649                         bi = yaffs_GetBlockInfo(dev, i);
3650                         //yaffs_VerifyBlock(dev,bi,i);
3651 -
3652 +                       
3653                         if(bi->gcPrioritise) {
3654                                 pendingPrioritisedExist = 1;
3655                                 if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3656 @@ -2610,7 +2684,7 @@ static int yaffs_FindBlockForGarbageColl
3657                                 }
3658                         }
3659                 }
3660 -
3661 +               
3662                 if(!pendingPrioritisedExist) /* None found, so we can clear this */
3663                         dev->hasPendingPrioritisedGCs = 0;
3664         }
3665 @@ -2662,7 +2736,7 @@ static int yaffs_FindBlockForGarbageColl
3666                         dirtiest = b;
3667                         pagesInUse = 0;
3668                 }
3669 -               else
3670 +               else 
3671  #endif
3672  
3673                 if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3674 @@ -2699,11 +2773,11 @@ static void yaffs_BlockBecameDirty(yaffs
3675         /* If the block is still healthy erase it and mark as clean.
3676          * If the block has had a data failure, then retire it.
3677          */
3678 -
3679 +        
3680         T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
3681                 (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
3682                 blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
3683 -
3684 +               
3685         bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
3686  
3687         if (!bi->needsRetiring) {
3688 @@ -2716,7 +2790,7 @@ static void yaffs_BlockBecameDirty(yaffs
3689                 }
3690         }
3691  
3692 -       if (erasedOk &&
3693 +       if (erasedOk && 
3694             ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) {
3695                 int i;
3696                 for (i = 0; i < dev->nChunksPerBlock; i++) {
3697 @@ -2763,11 +2837,11 @@ static int yaffs_FindBlockForAllocation(
3698                  * Can't get space to gc
3699                  */
3700                 T(YAFFS_TRACE_ERROR,
3701 -                 (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
3702 +                 (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));
3703  
3704                 return -1;
3705         }
3706 -
3707 +       
3708         /* Find an empty block. */
3709  
3710         for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
3711 @@ -2794,13 +2868,48 @@ static int yaffs_FindBlockForAllocation(
3712  
3713         T(YAFFS_TRACE_ALWAYS,
3714           (TSTR
3715 -          ("yaffs tragedy: no more eraased blocks, but there should have been %d"
3716 +          ("yaffs tragedy: no more erased blocks, but there should have been %d"
3717             TENDSTR), dev->nErasedBlocks));
3718  
3719         return -1;
3720  }
3721  
3722  
3723 +
3724 +static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
3725 +{
3726 +       if(!dev->nCheckpointBlocksRequired &&
3727 +          dev->isYaffs2){
3728 +               /* Not a valid value so recalculate */
3729 +               int nBytes = 0;
3730 +               int nBlocks;
3731 +               int devBlocks = (dev->endBlock - dev->startBlock + 1);
3732 +               int tnodeSize;
3733 +
3734 +               tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
3735 +
3736 +               if(tnodeSize < sizeof(yaffs_Tnode))
3737 +                       tnodeSize = sizeof(yaffs_Tnode);
3738 +               
3739 +               nBytes += sizeof(yaffs_CheckpointValidity);
3740 +               nBytes += sizeof(yaffs_CheckpointDevice);
3741 +               nBytes += devBlocks * sizeof(yaffs_BlockInfo);
3742 +               nBytes += devBlocks * dev->chunkBitmapStride;
3743 +               nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects);
3744 +               nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes);
3745 +               nBytes += sizeof(yaffs_CheckpointValidity);
3746 +               nBytes += sizeof(__u32); /* checksum*/
3747 +       
3748 +               /* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
3749 +       
3750 +               nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3;
3751 +       
3752 +               dev->nCheckpointBlocksRequired = nBlocks;
3753 +       }
3754 +
3755 +       return dev->nCheckpointBlocksRequired;
3756 +}
3757 +
3758  // Check if there's space to allocate...
3759  // Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
3760  static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
3761 @@ -2808,13 +2917,18 @@ static int yaffs_CheckSpaceForAllocation
3762         int reservedChunks;
3763         int reservedBlocks = dev->nReservedBlocks;
3764         int checkpointBlocks;
3765 -
3766 -       checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
3767 -       if(checkpointBlocks < 0)
3768 -               checkpointBlocks = 0;
3769 -
3770 +       
3771 +       if(dev->isYaffs2){
3772 +               checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - 
3773 +                                   dev->blocksInCheckpoint;
3774 +               if(checkpointBlocks < 0)
3775 +                       checkpointBlocks = 0;
3776 +       } else {
3777 +               checkpointBlocks =0;
3778 +       }
3779 +       
3780         reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
3781 -
3782 +       
3783         return (dev->nFreeChunks > reservedChunks);
3784  }
3785  
3786 @@ -2861,10 +2975,10 @@ static int yaffs_AllocateChunk(yaffs_Dev
3787  
3788                 if(blockUsedPtr)
3789                         *blockUsedPtr = bi;
3790 -
3791 +                       
3792                 return retVal;
3793         }
3794 -
3795 +       
3796         T(YAFFS_TRACE_ERROR,
3797           (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
3798  
3799 @@ -2885,17 +2999,17 @@ static int yaffs_GetErasedChunks(yaffs_D
3800  
3801  }
3802  
3803 -static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
3804 +static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlock)
3805  {
3806         int oldChunk;
3807         int newChunk;
3808 -       int chunkInBlock;
3809         int markNAND;
3810         int retVal = YAFFS_OK;
3811         int cleanups = 0;
3812         int i;
3813         int isCheckpointBlock;
3814         int matchingChunk;
3815 +       int maxCopies;
3816  
3817         int chunksBefore = yaffs_GetErasedChunks(dev);
3818         int chunksAfter;
3819 @@ -2907,12 +3021,15 @@ static int yaffs_GarbageCollectBlock(yaf
3820         yaffs_Object *object;
3821  
3822         isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
3823 -
3824 +       
3825         bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
3826  
3827         T(YAFFS_TRACE_TRACING,
3828 -         (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
3829 -          bi->pagesInUse, bi->hasShrinkHeader));
3830 +         (TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR), 
3831 +         block,
3832 +         bi->pagesInUse,
3833 +         bi->hasShrinkHeader,
3834 +         wholeBlock));
3835  
3836         /*yaffs_VerifyFreeChunks(dev); */
3837  
3838 @@ -2935,16 +3052,23 @@ static int yaffs_GarbageCollectBlock(yaf
3839         } else {
3840  
3841                 __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
3842 -
3843 +               
3844                 yaffs_VerifyBlock(dev,bi,block);
3845  
3846 -               for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
3847 -                    chunkInBlock < dev->nChunksPerBlock
3848 -                    && yaffs_StillSomeChunkBits(dev, block);
3849 -                    chunkInBlock++, oldChunk++) {
3850 -                       if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
3851 +               maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10;
3852 +               oldChunk = block * dev->nChunksPerBlock + dev->gcChunk;
3853 +               
3854 +               for ( /* init already done */;
3855 +                    retVal == YAFFS_OK &&
3856 +                    dev->gcChunk < dev->nChunksPerBlock &&
3857 +                    (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING)&&
3858 +                    maxCopies > 0;
3859 +                    dev->gcChunk++, oldChunk++) {
3860 +                       if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) {
3861  
3862                                 /* This page is in use and might need to be copied off */
3863 +                               
3864 +                               maxCopies--;
3865  
3866                                 markNAND = 1;
3867  
3868 @@ -2959,23 +3083,23 @@ static int yaffs_GarbageCollectBlock(yaf
3869  
3870                                 T(YAFFS_TRACE_GC_DETAIL,
3871                                   (TSTR
3872 -                                  ("Collecting page %d, %d %d %d " TENDSTR),
3873 -                                  chunkInBlock, tags.objectId, tags.chunkId,
3874 +                                  ("Collecting chunk in block %d, %d %d %d " TENDSTR),
3875 +                                  dev->gcChunk, tags.objectId, tags.chunkId,
3876                                    tags.byteCount));
3877 -
3878 +                                  
3879                                 if(object && !yaffs_SkipVerification(dev)){
3880                                         if(tags.chunkId == 0)
3881 -                                               matchingChunk = object->chunkId;
3882 +                                               matchingChunk = object->hdrChunk;
3883                                         else if(object->softDeleted)
3884                                                 matchingChunk = oldChunk; /* Defeat the test */
3885                                         else
3886                                                 matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL);
3887 -
3888 +                                       
3889                                         if(oldChunk != matchingChunk)
3890                                                 T(YAFFS_TRACE_ERROR,
3891                                                   (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR),
3892                                                   oldChunk,matchingChunk,tags.objectId, tags.chunkId));
3893 -
3894 +                                               
3895                                 }
3896  
3897                                 if (!object) {
3898 @@ -2986,11 +3110,13 @@ static int yaffs_GarbageCollectBlock(yaf
3899                                             tags.objectId, tags.chunkId, tags.byteCount));
3900                                 }
3901  
3902 -                               if (object && object->deleted
3903 -                                   && tags.chunkId != 0) {
3904 -                                       /* Data chunk in a deleted file, throw it away
3905 +                               if (object && 
3906 +                                   object->deleted &&
3907 +                                   object->softDeleted &&
3908 +                                   tags.chunkId != 0) {
3909 +                                       /* Data chunk in a soft deleted file, throw it away
3910                                          * It's a soft deleted data chunk,
3911 -                                        * No need to copy this, just forget about it and
3912 +                                        * No need to copy this, just forget about it and 
3913                                          * fix up the object.
3914                                          */
3915  
3916 @@ -3009,7 +3135,7 @@ static int yaffs_GarbageCollectBlock(yaf
3917                                         /* Deleted object header with no data chunks.
3918                                          * Can be discarded and the file deleted.
3919                                          */
3920 -                                       object->chunkId = 0;
3921 +                                       object->hdrChunk = 0;
3922                                         yaffs_FreeTnode(object->myDev,
3923                                                         object->variant.
3924                                                         fileVariant.top);
3925 @@ -3037,10 +3163,9 @@ static int yaffs_GarbageCollectBlock(yaf
3926                                                 yaffs_ObjectHeader *oh;
3927                                                 oh = (yaffs_ObjectHeader *)buffer;
3928                                                 oh->isShrink = 0;
3929 -                                               oh->shadowsObject = -1;
3930                                                 tags.extraShadows = 0;
3931                                                 tags.extraIsShrinkHeader = 0;
3932 -
3933 +                                               
3934                                                 yaffs_VerifyObjectHeader(object,oh,&tags,1);
3935                                         }
3936  
3937 @@ -3055,7 +3180,7 @@ static int yaffs_GarbageCollectBlock(yaf
3938  
3939                                                 if (tags.chunkId == 0) {
3940                                                         /* It's a header */
3941 -                                                       object->chunkId =  newChunk;
3942 +                                                       object->hdrChunk =  newChunk;
3943                                                         object->serial =   tags.serialNumber;
3944                                                 } else {
3945                                                         /* It's a data chunk */
3946 @@ -3067,12 +3192,14 @@ static int yaffs_GarbageCollectBlock(yaf
3947                                         }
3948                                 }
3949  
3950 -                               yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
3951 +                               if(retVal == YAFFS_OK)
3952 +                                       yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
3953  
3954                         }
3955                 }
3956  
3957                 yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
3958 +               
3959  
3960  
3961                 /* Do any required cleanups */
3962 @@ -3099,7 +3226,7 @@ static int yaffs_GarbageCollectBlock(yaf
3963         }
3964  
3965         yaffs_VerifyCollectedBlock(dev,bi,block);
3966 -
3967 +         
3968         if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
3969                 T(YAFFS_TRACE_GC,
3970                   (TSTR
3971 @@ -3107,9 +3234,15 @@ static int yaffs_GarbageCollectBlock(yaf
3972                     TENDSTR), chunksBefore, chunksAfter));
3973         }
3974  
3975 +       /* If the gc completed then clear the current gcBlock so that we find another. */
3976 +       if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING){
3977 +               dev->gcBlock = -1;
3978 +               dev->gcChunk = 0;
3979 +       }
3980 +       
3981         dev->isDoingGC = 0;
3982  
3983 -       return YAFFS_OK;
3984 +       return retVal;
3985  }
3986  
3987  /* New garbage collector
3988 @@ -3127,22 +3260,22 @@ static int yaffs_CheckGarbageCollection(
3989         int aggressive;
3990         int gcOk = YAFFS_OK;
3991         int maxTries = 0;
3992 -
3993 +       
3994         int checkpointBlockAdjust;
3995  
3996         if (dev->isDoingGC) {
3997                 /* Bail out so we don't get recursive gc */
3998                 return YAFFS_OK;
3999         }
4000 -
4001 +       
4002         /* This loop should pass the first time.
4003          * We'll only see looping here if the erase of the collected block fails.
4004          */
4005  
4006         do {
4007                 maxTries++;
4008 -
4009 -               checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
4010 +               
4011 +               checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
4012                 if(checkpointBlockAdjust < 0)
4013                         checkpointBlockAdjust = 0;
4014  
4015 @@ -3154,7 +3287,12 @@ static int yaffs_CheckGarbageCollection(
4016                         aggressive = 0;
4017                 }
4018  
4019 -               block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
4020 +               if(dev->gcBlock <= 0){
4021 +                       dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive);
4022 +                       dev->gcChunk = 0;
4023 +               }
4024 +               
4025 +               block = dev->gcBlock;
4026  
4027                 if (block > 0) {
4028                         dev->garbageCollections++;
4029 @@ -3167,7 +3305,7 @@ static int yaffs_CheckGarbageCollection(
4030                            ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
4031                            dev->nErasedBlocks, aggressive));
4032  
4033 -                       gcOk = yaffs_GarbageCollectBlock(dev, block);
4034 +                       gcOk = yaffs_GarbageCollectBlock(dev,block,aggressive);
4035                 }
4036  
4037                 if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
4038 @@ -3176,8 +3314,9 @@ static int yaffs_CheckGarbageCollection(
4039                            ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
4040                             TENDSTR), dev->nErasedBlocks, maxTries, block));
4041                 }
4042 -       } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
4043 -                && (maxTries < 2));
4044 +       } while ((dev->nErasedBlocks < dev->nReservedBlocks) && 
4045 +                (block > 0) &&
4046 +                (maxTries < 2));
4047  
4048         return aggressive ? gcOk : YAFFS_OK;
4049  }
4050 @@ -3326,11 +3465,11 @@ static int yaffs_CheckFileSanity(yaffs_O
4051  static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
4052                                   int chunkInNAND, int inScan)
4053  {
4054 -       /* NB inScan is zero unless scanning.
4055 -        * For forward scanning, inScan is > 0;
4056 +       /* NB inScan is zero unless scanning. 
4057 +        * For forward scanning, inScan is > 0; 
4058          * for backward scanning inScan is < 0
4059          */
4060 -
4061 +        
4062         yaffs_Tnode *tn;
4063         yaffs_Device *dev = in->myDev;
4064         int existingChunk;
4065 @@ -3354,7 +3493,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
4066                 return YAFFS_OK;
4067         }
4068  
4069 -       tn = yaffs_AddOrFindLevel0Tnode(dev,
4070 +       tn = yaffs_AddOrFindLevel0Tnode(dev, 
4071                                         &in->variant.fileVariant,
4072                                         chunkInInode,
4073                                         NULL);
4074 @@ -3366,7 +3505,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
4075  
4076         if (inScan != 0) {
4077                 /* If we're scanning then we need to test for duplicates
4078 -                * NB This does not need to be efficient since it should only ever
4079 +                * NB This does not need to be efficient since it should only ever 
4080                  * happen when the power fails during a write, then only one
4081                  * chunk should ever be affected.
4082                  *
4083 @@ -3374,7 +3513,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
4084                  * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
4085                  */
4086  
4087 -               if (existingChunk != 0) {
4088 +               if (existingChunk > 0) {
4089                         /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
4090                          *    thus we have to do a FindChunkInFile to get the real chunk id.
4091                          *
4092 @@ -3407,18 +3546,20 @@ static int yaffs_PutChunkIntoFile(yaffs_
4093  
4094                         }
4095  
4096 -                       /* NB The deleted flags should be false, otherwise the chunks will
4097 +                       /* NB The deleted flags should be false, otherwise the chunks will 
4098                          * not be loaded during a scan
4099                          */
4100  
4101 -                       newSerial = newTags.serialNumber;
4102 -                       existingSerial = existingTags.serialNumber;
4103 +                       if(inScan > 0) {
4104 +                               newSerial = newTags.serialNumber;
4105 +                               existingSerial = existingTags.serialNumber;
4106 +                       }
4107  
4108                         if ((inScan > 0) &&
4109                             (in->myDev->isYaffs2 ||
4110                              existingChunk <= 0 ||
4111                              ((existingSerial + 1) & 3) == newSerial)) {
4112 -                               /* Forward scanning.
4113 +                               /* Forward scanning.                            
4114                                  * Use new
4115                                  * Delete the old one and drop through to update the tnode
4116                                  */
4117 @@ -3459,7 +3600,7 @@ static int yaffs_ReadChunkDataFromObject
4118                   (TSTR("Chunk %d not found zero instead" TENDSTR),
4119                    chunkInNAND));
4120                 /* get sane (zero) data if you read a hole */
4121 -               memset(buffer, 0, in->myDev->nDataBytesPerChunk);
4122 +               memset(buffer, 0, in->myDev->nDataBytesPerChunk);       
4123                 return 0;
4124         }
4125  
4126 @@ -3474,7 +3615,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
4127  
4128         if (chunkId <= 0)
4129                 return;
4130 -
4131 +               
4132  
4133         dev->nDeletions++;
4134         block = chunkId / dev->nChunksPerBlock;
4135 @@ -3560,6 +3701,14 @@ static int yaffs_WriteChunkDataToObject(
4136         newTags.serialNumber =
4137             (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
4138         newTags.byteCount = nBytes;
4139 +       
4140 +       if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){
4141 +         T(YAFFS_TRACE_ERROR,
4142 +         (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
4143 +         while(1){}
4144 +        }
4145 +       
4146 +       
4147  
4148         newChunkId =
4149             yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
4150 @@ -3601,11 +3750,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
4151         __u8 *buffer = NULL;
4152         YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
4153  
4154 -       yaffs_ObjectHeader *oh = NULL;
4155 +        yaffs_ObjectHeader *oh = NULL;
4156 +        
4157 +        yaffs_strcpy(oldName,_Y("silly old name"));
4158  
4159 -       yaffs_strcpy(oldName,"silly old name");
4160  
4161 -       if (!in->fake || force) {
4162 +       if (!in->fake || 
4163 +           in == dev->rootDir || /* The rootDir should also be saved */
4164 +           force) {
4165  
4166                 yaffs_CheckGarbageCollection(dev);
4167                 yaffs_CheckObjectDetailsLoaded(in);
4168 @@ -3613,14 +3765,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
4169                 buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
4170                 oh = (yaffs_ObjectHeader *) buffer;
4171  
4172 -               prevChunkId = in->chunkId;
4173 +               prevChunkId = in->hdrChunk;
4174  
4175 -               if (prevChunkId >= 0) {
4176 +               if (prevChunkId > 0) {
4177                         result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
4178                                                         buffer, &oldTags);
4179 -
4180 +                       
4181                         yaffs_VerifyObjectHeader(in,oh,&oldTags,0);
4182 -
4183 +                                                                               
4184                         memcpy(oldName, oh->name, sizeof(oh->name));
4185                 }
4186  
4187 @@ -3628,7 +3780,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
4188  
4189                 oh->type = in->variantType;
4190                 oh->yst_mode = in->yst_mode;
4191 -               oh->shadowsObject = shadows;
4192 +               oh->shadowsObject = oh->inbandShadowsObject = shadows;
4193  
4194  #ifdef CONFIG_YAFFS_WINCE
4195                 oh->win_atime[0] = in->win_atime[0];
4196 @@ -3717,7 +3869,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
4197  
4198                 if (newChunkId >= 0) {
4199  
4200 -                       in->chunkId = newChunkId;
4201 +                       in->hdrChunk = newChunkId;
4202  
4203                         if (prevChunkId >= 0) {
4204                                 yaffs_DeleteChunk(dev, prevChunkId, 1,
4205 @@ -3748,11 +3900,11 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
4206  
4207  /*------------------------ Short Operations Cache ----------------------------------------
4208   *   In many situations where there is no high level buffering (eg WinCE) a lot of
4209 - *   reads might be short sequential reads, and a lot of writes may be short
4210 + *   reads might be short sequential reads, and a lot of writes may be short 
4211   *   sequential writes. eg. scanning/writing a jpeg file.
4212 - *   In these cases, a short read/write cache can provide a huge perfomance benefit
4213 + *   In these cases, a short read/write cache can provide a huge perfomance benefit 
4214   *   with dumb-as-a-rock code.
4215 - *   In Linux, the page cache provides read buffering aand the short op cache provides write
4216 + *   In Linux, the page cache provides read buffering aand the short op cache provides write 
4217   *   buffering.
4218   *
4219   *   There are a limited number (~10) of cache chunks per device so that we don't
4220 @@ -3765,14 +3917,14 @@ static int yaffs_ObjectHasCachedWriteDat
4221         int i;
4222         yaffs_ChunkCache *cache;
4223         int nCaches = obj->myDev->nShortOpCaches;
4224 -
4225 +       
4226         for(i = 0; i < nCaches; i++){
4227                 cache = &dev->srCache[i];
4228                 if (cache->object == obj &&
4229                     cache->dirty)
4230                         return 1;
4231         }
4232 -
4233 +       
4234         return 0;
4235  }
4236  
4237 @@ -3838,7 +3990,7 @@ void yaffs_FlushEntireDeviceCache(yaffs_
4238         yaffs_Object *obj;
4239         int nCaches = dev->nShortOpCaches;
4240         int i;
4241 -
4242 +       
4243         /* Find a dirty object in the cache and flush it...
4244          * until there are no further dirty objects.
4245          */
4246 @@ -3848,53 +4000,33 @@ void yaffs_FlushEntireDeviceCache(yaffs_
4247                         if (dev->srCache[i].object &&
4248                             dev->srCache[i].dirty)
4249                                 obj = dev->srCache[i].object;
4250 -
4251 +                           
4252                 }
4253                 if(obj)
4254                         yaffs_FlushFilesChunkCache(obj);
4255 -
4256 +                       
4257         } while(obj);
4258 -
4259 +       
4260  }
4261  
4262  
4263  /* Grab us a cache chunk for use.
4264 - * First look for an empty one.
4265 + * First look for an empty one. 
4266   * Then look for the least recently used non-dirty one.
4267   * Then look for the least recently used dirty one...., flush and look again.
4268   */
4269  static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
4270  {
4271         int i;
4272 -       int usage;
4273 -       int theOne;
4274  
4275         if (dev->nShortOpCaches > 0) {
4276                 for (i = 0; i < dev->nShortOpCaches; i++) {
4277 -                       if (!dev->srCache[i].object)
4278 +                       if (!dev->srCache[i].object) 
4279                                 return &dev->srCache[i];
4280                 }
4281 -
4282 -               return NULL;
4283 -
4284 -               theOne = -1;
4285 -               usage = 0;      /* just to stop the compiler grizzling */
4286 -
4287 -               for (i = 0; i < dev->nShortOpCaches; i++) {
4288 -                       if (!dev->srCache[i].dirty &&
4289 -                           ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
4290 -                            theOne < 0)) {
4291 -                               usage = dev->srCache[i].lastUse;
4292 -                               theOne = i;
4293 -                       }
4294 -               }
4295 -
4296 -
4297 -               return theOne >= 0 ? &dev->srCache[theOne] : NULL;
4298 -       } else {
4299 -               return NULL;
4300         }
4301  
4302 +       return NULL;
4303  }
4304  
4305  static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
4306 @@ -4032,14 +4164,14 @@ static void yaffs_InvalidateWholeChunkCa
4307  static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
4308  {
4309         yaffs_CheckpointValidity cp;
4310 -
4311 +       
4312         memset(&cp,0,sizeof(cp));
4313 -
4314 +       
4315         cp.structType = sizeof(cp);
4316         cp.magic = YAFFS_MAGIC;
4317         cp.version = YAFFS_CHECKPOINT_VERSION;
4318         cp.head = (head) ? 1 : 0;
4319 -
4320 +       
4321         return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
4322                 1 : 0;
4323  }
4324 @@ -4048,9 +4180,9 @@ static int yaffs_ReadCheckpointValidityM
4325  {
4326         yaffs_CheckpointValidity cp;
4327         int ok;
4328 -
4329 +       
4330         ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
4331 -
4332 +       
4333         if(ok)
4334                 ok = (cp.structType == sizeof(cp)) &&
4335                      (cp.magic == YAFFS_MAGIC) &&
4336 @@ -4059,20 +4191,20 @@ static int yaffs_ReadCheckpointValidityM
4337         return ok ? 1 : 0;
4338  }
4339  
4340 -static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
4341 +static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, 
4342                                            yaffs_Device *dev)
4343  {
4344         cp->nErasedBlocks = dev->nErasedBlocks;
4345         cp->allocationBlock = dev->allocationBlock;
4346         cp->allocationPage = dev->allocationPage;
4347         cp->nFreeChunks = dev->nFreeChunks;
4348 -
4349 +       
4350         cp->nDeletedFiles = dev->nDeletedFiles;
4351         cp->nUnlinkedFiles = dev->nUnlinkedFiles;
4352         cp->nBackgroundDeletions = dev->nBackgroundDeletions;
4353         cp->sequenceNumber = dev->sequenceNumber;
4354         cp->oldestDirtySequence = dev->oldestDirtySequence;
4355 -
4356 +       
4357  }
4358  
4359  static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
4360 @@ -4082,7 +4214,7 @@ static void yaffs_CheckpointDeviceToDevi
4361         dev->allocationBlock = cp->allocationBlock;
4362         dev->allocationPage = cp->allocationPage;
4363         dev->nFreeChunks = cp->nFreeChunks;
4364 -
4365 +       
4366         dev->nDeletedFiles = cp->nDeletedFiles;
4367         dev->nUnlinkedFiles = cp->nUnlinkedFiles;
4368         dev->nBackgroundDeletions = cp->nBackgroundDeletions;
4369 @@ -4098,20 +4230,20 @@ static int yaffs_WriteCheckpointDevice(y
4370         __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
4371  
4372         int ok;
4373 -
4374 +               
4375         /* Write device runtime values*/
4376         yaffs_DeviceToCheckpointDevice(&cp,dev);
4377         cp.structType = sizeof(cp);
4378 -
4379 +       
4380         ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4381 -
4382 +       
4383         /* Write block info */
4384         if(ok) {
4385                 nBytes = nBlocks * sizeof(yaffs_BlockInfo);
4386                 ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
4387         }
4388 -
4389 -       /* Write chunk bits */
4390 +               
4391 +       /* Write chunk bits */          
4392         if(ok) {
4393                 nBytes = nBlocks * dev->chunkBitmapStride;
4394                 ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
4395 @@ -4126,28 +4258,28 @@ static int yaffs_ReadCheckpointDevice(ya
4396         __u32 nBytes;
4397         __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
4398  
4399 -       int ok;
4400 -
4401 +       int ok; 
4402 +       
4403         ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
4404         if(!ok)
4405                 return 0;
4406 -
4407 +               
4408         if(cp.structType != sizeof(cp))
4409                 return 0;
4410 -
4411 -
4412 +               
4413 +       
4414         yaffs_CheckpointDeviceToDevice(dev,&cp);
4415 -
4416 +       
4417         nBytes = nBlocks * sizeof(yaffs_BlockInfo);
4418 -
4419 +       
4420         ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
4421 -
4422 +       
4423         if(!ok)
4424                 return 0;
4425         nBytes = nBlocks * dev->chunkBitmapStride;
4426 -
4427 +       
4428         ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
4429 -
4430 +       
4431         return ok ? 1 : 0;
4432  }
4433  
4434 @@ -4157,7 +4289,7 @@ static void yaffs_ObjectToCheckpointObje
4435  
4436         cp->objectId = obj->objectId;
4437         cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
4438 -       cp->chunkId = obj->chunkId;
4439 +       cp->hdrChunk = obj->hdrChunk;
4440         cp->variantType = obj->variantType;
4441         cp->deleted = obj->deleted;
4442         cp->softDeleted = obj->softDeleted;
4443 @@ -4167,7 +4299,7 @@ static void yaffs_ObjectToCheckpointObje
4444         cp->unlinkAllowed = obj->unlinkAllowed;
4445         cp->serial = obj->serial;
4446         cp->nDataChunks = obj->nDataChunks;
4447 -
4448 +       
4449         if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
4450                 cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
4451         else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
4452 @@ -4178,9 +4310,9 @@ static void yaffs_CheckpointObjectToObje
4453  {
4454  
4455         yaffs_Object *parent;
4456 -
4457 +       
4458         obj->objectId = cp->objectId;
4459 -
4460 +       
4461         if(cp->parentId)
4462                 parent = yaffs_FindOrCreateObjectByNumber(
4463                                         obj->myDev,
4464 @@ -4188,11 +4320,11 @@ static void yaffs_CheckpointObjectToObje
4465                                         YAFFS_OBJECT_TYPE_DIRECTORY);
4466         else
4467                 parent = NULL;
4468 -
4469 +               
4470         if(parent)
4471                 yaffs_AddObjectToDirectory(parent, obj);
4472  
4473 -       obj->chunkId = cp->chunkId;
4474 +       obj->hdrChunk = cp->hdrChunk;
4475         obj->variantType = cp->variantType;
4476         obj->deleted = cp->deleted;
4477         obj->softDeleted = cp->softDeleted;
4478 @@ -4202,13 +4334,13 @@ static void yaffs_CheckpointObjectToObje
4479         obj->unlinkAllowed = cp->unlinkAllowed;
4480         obj->serial = cp->serial;
4481         obj->nDataChunks = cp->nDataChunks;
4482 -
4483 +       
4484         if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
4485                 obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
4486         else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
4487                 obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
4488  
4489 -       if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
4490 +       if(obj->hdrChunk > 0)
4491                 obj->lazyLoaded = 1;
4492  }
4493  
4494 @@ -4220,7 +4352,11 @@ static int yaffs_CheckpointTnodeWorker(y
4495         int i;
4496         yaffs_Device *dev = in->myDev;
4497         int ok = 1;
4498 -       int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4499 +       int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4500 +
4501 +       if(tnodeSize < sizeof(yaffs_Tnode))
4502 +               tnodeSize = sizeof(yaffs_Tnode);
4503 +       
4504  
4505         if (tn) {
4506                 if (level > 0) {
4507 @@ -4235,10 +4371,9 @@ static int yaffs_CheckpointTnodeWorker(y
4508                         }
4509                 } else if (level == 0) {
4510                         __u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
4511 -                       /* printf("write tnode at %d\n",baseOffset); */
4512                         ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
4513                         if(ok)
4514 -                               ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
4515 +                               ok = (yaffs_CheckpointWrite(dev,tn,tnodeSize) == tnodeSize);
4516                 }
4517         }
4518  
4519 @@ -4250,17 +4385,17 @@ static int yaffs_WriteCheckpointTnodes(y
4520  {
4521         __u32 endMarker = ~0;
4522         int ok = 1;
4523 -
4524 +       
4525         if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
4526                 ok = yaffs_CheckpointTnodeWorker(obj,
4527                                             obj->variant.fileVariant.top,
4528                                             obj->variant.fileVariant.topLevel,
4529                                             0);
4530                 if(ok)
4531 -                       ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
4532 +                       ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == 
4533                                 sizeof(endMarker));
4534         }
4535 -
4536 +       
4537         return ok ? 1 : 0;
4538  }
4539  
4540 @@ -4272,70 +4407,72 @@ static int yaffs_ReadCheckpointTnodes(ya
4541         yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
4542         yaffs_Tnode *tn;
4543         int nread = 0;
4544 +       int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4545  
4546 -       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4547 +       if(tnodeSize < sizeof(yaffs_Tnode))
4548 +               tnodeSize = sizeof(yaffs_Tnode);
4549  
4550 +       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4551 +       
4552         while(ok && (~baseChunk)){
4553                 nread++;
4554                 /* Read level 0 tnode */
4555 -
4556 -
4557 -               /* printf("read  tnode at %d\n",baseChunk); */
4558 +               
4559 +               
4560                 tn = yaffs_GetTnodeRaw(dev);
4561                 if(tn)
4562 -                       ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
4563 -                             (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
4564 +                       ok = (yaffs_CheckpointRead(dev,tn,tnodeSize) == tnodeSize);
4565                 else
4566                         ok = 0;
4567 -
4568 +                       
4569                 if(tn && ok){
4570                         ok = yaffs_AddOrFindLevel0Tnode(dev,
4571                                                         fileStructPtr,
4572                                                         baseChunk,
4573                                                         tn) ? 1 : 0;
4574 -
4575 +                                                       
4576                 }
4577 -
4578 +                       
4579                 if(ok)
4580                         ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4581 -
4582 +               
4583         }
4584  
4585         T(YAFFS_TRACE_CHECKPOINT,(
4586                 TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR),
4587                 nread,baseChunk,ok));
4588  
4589 -       return ok ? 1 : 0;
4590 +       return ok ? 1 : 0;      
4591  }
4592 -
4593
4594  
4595  static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
4596  {
4597         yaffs_Object *obj;
4598 -       yaffs_CheckpointObject cp;
4599 -       int i;
4600 -       int ok = 1;
4601 -       struct list_head *lh;
4602 +        yaffs_CheckpointObject cp;
4603 +        int i;
4604 +        int ok = 1;
4605 +        struct ylist_head *lh;
4606  
4607 -
4608 -       /* Iterate through the objects in each hash entry,
4609 +        
4610 +        /* Iterate through the objects in each hash entry,
4611          * dumping them to the checkpointing stream.
4612 -        */
4613 -
4614 -        for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
4615 -               list_for_each(lh, &dev->objectBucket[i].list) {
4616 -                       if (lh) {
4617 -                               obj = list_entry(lh, yaffs_Object, hashLink);
4618 -                               if (!obj->deferedFree) {
4619 -                                       yaffs_ObjectToCheckpointObject(&cp,obj);
4620 -                                       cp.structType = sizeof(cp);
4621 +         */
4622 +         
4623 +         for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
4624 +                ylist_for_each(lh, &dev->objectBucket[i].list) {
4625 +                        if (lh) {
4626 +                                obj = ylist_entry(lh, yaffs_Object, hashLink);
4627 +                                if (!obj->deferedFree) {
4628 +                                        yaffs_ObjectToCheckpointObject(&cp,obj);
4629 +                                        cp.structType = sizeof(cp);
4630  
4631                                         T(YAFFS_TRACE_CHECKPOINT,(
4632                                                 TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
4633 -                                               cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
4634 +                                               cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk,(unsigned) obj));
4635  
4636                                         ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4637 -
4638 +                                       
4639                                         if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
4640                                                 ok = yaffs_WriteCheckpointTnodes(obj);
4641                                         }
4642 @@ -4343,14 +4480,14 @@ static int yaffs_WriteCheckpointObjects(
4643                         }
4644                 }
4645          }
4646 -
4647 +        
4648          /* Dump end of list */
4649         memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
4650         cp.structType = sizeof(cp);
4651 -
4652 +       
4653         if(ok)
4654                 ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4655 -
4656 +               
4657         return ok ? 1 : 0;
4658  }
4659  
4660 @@ -4361,7 +4498,7 @@ static int yaffs_ReadCheckpointObjects(y
4661         int ok = 1;
4662         int done = 0;
4663         yaffs_Object *hardList = NULL;
4664 -
4665 +       
4666         while(ok && !done) {
4667                 ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
4668                 if(cp.structType != sizeof(cp)) {
4669 @@ -4369,9 +4506,9 @@ static int yaffs_ReadCheckpointObjects(y
4670                                 cp.structType,sizeof(cp),ok));
4671                         ok = 0;
4672                 }
4673 -
4674 +                       
4675                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
4676 -                       cp.objectId,cp.parentId,cp.variantType,cp.chunkId));
4677 +                       cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk));
4678  
4679                 if(ok && cp.objectId == ~0)
4680                         done = 1;
4681 @@ -4380,21 +4517,21 @@ static int yaffs_ReadCheckpointObjects(y
4682                         if(obj) {
4683                                 yaffs_CheckpointObjectToObject(obj,&cp);
4684                                 if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
4685 -                                       ok = yaffs_ReadCheckpointTnodes(obj);
4686 -                               } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4687 -                                       obj->hardLinks.next =
4688 -                                                   (struct list_head *)
4689 -                                                   hardList;
4690 -                                       hardList = obj;
4691 -                               }
4692 -
4693 +                                        ok = yaffs_ReadCheckpointTnodes(obj);
4694 +                                } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4695 +                                        obj->hardLinks.next =
4696 +                                                    (struct ylist_head *)
4697 +                                                    hardList;
4698 +                                        hardList = obj;
4699 +                                }
4700 +                          
4701                         }
4702                 }
4703         }
4704 -
4705 +       
4706         if(ok)
4707                 yaffs_HardlinkFixup(dev,hardList);
4708 -
4709 +       
4710         return ok ? 1 : 0;
4711  }
4712  
4713 @@ -4402,14 +4539,14 @@ static int yaffs_WriteCheckpointSum(yaff
4714  {
4715         __u32 checkpointSum;
4716         int ok;
4717 -
4718 +       
4719         yaffs_GetCheckpointSum(dev,&checkpointSum);
4720 -
4721 +       
4722         ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum));
4723 -
4724 +       
4725         if(!ok)
4726                 return 0;
4727 -
4728 +       
4729         return 1;
4730  }
4731  
4732 @@ -4418,17 +4555,17 @@ static int yaffs_ReadCheckpointSum(yaffs
4733         __u32 checkpointSum0;
4734         __u32 checkpointSum1;
4735         int ok;
4736 -
4737 +       
4738         yaffs_GetCheckpointSum(dev,&checkpointSum0);
4739 -
4740 +       
4741         ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1));
4742 -
4743 +       
4744         if(!ok)
4745                 return 0;
4746 -
4747 +               
4748         if(checkpointSum0 != checkpointSum1)
4749                 return 0;
4750 -
4751 +       
4752         return 1;
4753  }
4754  
4755 @@ -4437,15 +4574,15 @@ static int yaffs_WriteCheckpointData(yaf
4756  {
4757  
4758         int ok = 1;
4759 -
4760 +       
4761         if(dev->skipCheckpointWrite || !dev->isYaffs2){
4762                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR)));
4763                 ok = 0;
4764         }
4765 -
4766 +               
4767         if(ok)
4768                 ok = yaffs_CheckpointOpen(dev,1);
4769 -
4770 +       
4771         if(ok){
4772                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
4773                 ok = yaffs_WriteCheckpointValidityMarker(dev,1);
4774 @@ -4462,18 +4599,18 @@ static int yaffs_WriteCheckpointData(yaf
4775                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
4776                 ok = yaffs_WriteCheckpointValidityMarker(dev,0);
4777         }
4778 -
4779 +       
4780         if(ok){
4781                 ok = yaffs_WriteCheckpointSum(dev);
4782         }
4783 -
4784 -
4785 +       
4786 +       
4787         if(!yaffs_CheckpointClose(dev))
4788                  ok = 0;
4789 -
4790 +                
4791         if(ok)
4792                 dev->isCheckpointed = 1;
4793 -        else
4794 +        else 
4795                 dev->isCheckpointed = 0;
4796  
4797         return dev->isCheckpointed;
4798 @@ -4482,17 +4619,17 @@ static int yaffs_WriteCheckpointData(yaf
4799  static int yaffs_ReadCheckpointData(yaffs_Device *dev)
4800  {
4801         int ok = 1;
4802 -
4803 +       
4804         if(dev->skipCheckpointRead || !dev->isYaffs2){
4805                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR)));
4806                 ok = 0;
4807         }
4808 -
4809 +       
4810         if(ok)
4811                 ok = yaffs_CheckpointOpen(dev,0); /* open for read */
4812 -
4813 +       
4814         if(ok){
4815 -               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4816 +               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));   
4817                 ok = yaffs_ReadCheckpointValidityMarker(dev,1);
4818         }
4819         if(ok){
4820 @@ -4500,14 +4637,14 @@ static int yaffs_ReadCheckpointData(yaff
4821                 ok = yaffs_ReadCheckpointDevice(dev);
4822         }
4823         if(ok){
4824 -               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
4825 +               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));    
4826                 ok = yaffs_ReadCheckpointObjects(dev);
4827         }
4828         if(ok){
4829                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4830                 ok = yaffs_ReadCheckpointValidityMarker(dev,0);
4831         }
4832 -
4833 +       
4834         if(ok){
4835                 ok = yaffs_ReadCheckpointSum(dev);
4836                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok));
4837 @@ -4518,7 +4655,7 @@ static int yaffs_ReadCheckpointData(yaff
4838  
4839         if(ok)
4840                 dev->isCheckpointed = 1;
4841 -        else
4842 +        else 
4843                 dev->isCheckpointed = 0;
4844  
4845         return ok ? 1 : 0;
4846 @@ -4527,7 +4664,7 @@ static int yaffs_ReadCheckpointData(yaff
4847  
4848  static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
4849  {
4850 -       if(dev->isCheckpointed ||
4851 +       if(dev->isCheckpointed || 
4852            dev->blocksInCheckpoint > 0){
4853                 dev->isCheckpointed = 0;
4854                 yaffs_CheckpointInvalidateStream(dev);
4855 @@ -4550,7 +4687,7 @@ int yaffs_CheckpointSave(yaffs_Device *d
4856                 yaffs_InvalidateCheckpoint(dev);
4857                 yaffs_WriteCheckpointData(dev);
4858         }
4859 -
4860 +       
4861         T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4862  
4863         return dev->isCheckpointed;
4864 @@ -4560,7 +4697,7 @@ int yaffs_CheckpointRestore(yaffs_Device
4865  {
4866         int retval;
4867         T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4868 -
4869 +               
4870         retval = yaffs_ReadCheckpointData(dev);
4871  
4872         if(dev->isCheckpointed){
4873 @@ -4570,7 +4707,7 @@ int yaffs_CheckpointRestore(yaffs_Device
4874         }
4875  
4876         T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4877 -
4878 +       
4879         return retval;
4880  }
4881  
4882 @@ -4589,7 +4726,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4883  {
4884  
4885         int chunk;
4886 -       int start;
4887 +       __u32 start;
4888         int nToCopy;
4889         int n = nBytes;
4890         int nDone = 0;
4891 @@ -4606,7 +4743,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4892                 chunk++;
4893  
4894                 /* OK now check for the curveball where the start and end are in
4895 -                * the same chunk.
4896 +                * the same chunk.      
4897                  */
4898                 if ((start + n) < dev->nDataBytesPerChunk) {
4899                         nToCopy = n;
4900 @@ -4617,10 +4754,10 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4901                 cache = yaffs_FindChunkCache(in, chunk);
4902  
4903                 /* If the chunk is already in the cache or it is less than a whole chunk
4904 -                * then use the cache (if there is caching)
4905 +                * or we're using inband tags then use the cache (if there is caching)
4906                  * else bypass the cache.
4907                  */
4908 -               if (cache || nToCopy != dev->nDataBytesPerChunk) {
4909 +               if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
4910                         if (dev->nShortOpCaches > 0) {
4911  
4912                                 /* If we can't find the data in the cache, then load it up. */
4913 @@ -4641,14 +4778,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4914  
4915                                 cache->locked = 1;
4916  
4917 -#ifdef CONFIG_YAFFS_WINCE
4918 -                               yfsd_UnlockYAFFS(TRUE);
4919 -#endif
4920 +
4921                                 memcpy(buffer, &cache->data[start], nToCopy);
4922  
4923 -#ifdef CONFIG_YAFFS_WINCE
4924 -                               yfsd_LockYAFFS(TRUE);
4925 -#endif
4926                                 cache->locked = 0;
4927                         } else {
4928                                 /* Read into the local buffer then copy..*/
4929 @@ -4657,41 +4789,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4930                                     yaffs_GetTempBuffer(dev, __LINE__);
4931                                 yaffs_ReadChunkDataFromObject(in, chunk,
4932                                                               localBuffer);
4933 -#ifdef CONFIG_YAFFS_WINCE
4934 -                               yfsd_UnlockYAFFS(TRUE);
4935 -#endif
4936 +
4937                                 memcpy(buffer, &localBuffer[start], nToCopy);
4938  
4939 -#ifdef CONFIG_YAFFS_WINCE
4940 -                               yfsd_LockYAFFS(TRUE);
4941 -#endif
4942 +
4943                                 yaffs_ReleaseTempBuffer(dev, localBuffer,
4944                                                         __LINE__);
4945                         }
4946  
4947                 } else {
4948 -#ifdef CONFIG_YAFFS_WINCE
4949 -                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4950 -
4951 -                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
4952 -                        * This is because we otherwise screw up WinCE's memory mapper
4953 -                        */
4954 -                       yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
4955 -
4956 -#ifdef CONFIG_YAFFS_WINCE
4957 -                       yfsd_UnlockYAFFS(TRUE);
4958 -#endif
4959 -                       memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
4960  
4961 -#ifdef CONFIG_YAFFS_WINCE
4962 -                       yfsd_LockYAFFS(TRUE);
4963 -                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
4964 -#endif
4965 -
4966 -#else
4967                         /* A full chunk. Read directly into the supplied buffer. */
4968                         yaffs_ReadChunkDataFromObject(in, chunk, buffer);
4969 -#endif
4970 +
4971                 }
4972  
4973                 n -= nToCopy;
4974 @@ -4709,14 +4819,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
4975  {
4976  
4977         int chunk;
4978 -       int start;
4979 +       __u32 start;
4980         int nToCopy;
4981 -       int n = nBytes;
4982 -       int nDone = 0;
4983 -       int nToWriteBack;
4984 -       int startOfWrite = offset;
4985 -       int chunkWritten = 0;
4986 -       int nBytesRead;
4987 +        int n = nBytes;
4988 +        int nDone = 0;
4989 +        int nToWriteBack;
4990 +        int startOfWrite = offset;
4991 +        int chunkWritten = 0;
4992 +        __u32 nBytesRead;
4993 +        __u32 chunkStart;
4994  
4995         yaffs_Device *dev;
4996  
4997 @@ -4726,6 +4837,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
4998                 //chunk = offset / dev->nDataBytesPerChunk + 1;
4999                 //start = offset % dev->nDataBytesPerChunk;
5000                 yaffs_AddrToChunk(dev,offset,&chunk,&start);
5001 +               
5002 +               if(chunk * dev->nDataBytesPerChunk + start != offset ||
5003 +                  start >= dev->nDataBytesPerChunk){
5004 +                  T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
5005 +                                       (int)offset, chunk,start));
5006 +               }
5007                 chunk++;
5008  
5009                 /* OK now check for the curveball where the start and end are in
5010 @@ -4740,9 +4857,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
5011                          * we need to write back as much as was there before.
5012                          */
5013  
5014 -                       nBytesRead =
5015 -                           in->variant.fileVariant.fileSize -
5016 -                           ((chunk - 1) * dev->nDataBytesPerChunk);
5017 +                       chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk);
5018 +
5019 +                       if(chunkStart > in->variant.fileVariant.fileSize)
5020 +                               nBytesRead = 0; /* Past end of file */
5021 +                       else
5022 +                               nBytesRead = in->variant.fileVariant.fileSize - chunkStart;
5023  
5024                         if (nBytesRead > dev->nDataBytesPerChunk) {
5025                                 nBytesRead = dev->nDataBytesPerChunk;
5026 @@ -4751,19 +4871,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
5027                         nToWriteBack =
5028                             (nBytesRead >
5029                              (start + n)) ? nBytesRead : (start + n);
5030 +                       
5031 +                       if(nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk)
5032 +                               YBUG();
5033  
5034                 } else {
5035                         nToCopy = dev->nDataBytesPerChunk - start;
5036                         nToWriteBack = dev->nDataBytesPerChunk;
5037                 }
5038  
5039 -               if (nToCopy != dev->nDataBytesPerChunk) {
5040 -                       /* An incomplete start or end chunk (or maybe both start and end chunk) */
5041 +               if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
5042 +                       /* An incomplete start or end chunk (or maybe both start and end chunk), 
5043 +                        * or we're using inband tags, so we want to use the cache buffers.
5044 +                        */
5045                         if (dev->nShortOpCaches > 0) {
5046                                 yaffs_ChunkCache *cache;
5047                                 /* If we can't find the data in the cache, then load the cache */
5048                                 cache = yaffs_FindChunkCache(in, chunk);
5049 -
5050 +                               
5051                                 if (!cache
5052                                     && yaffs_CheckSpaceForAllocation(in->
5053                                                                      myDev)) {
5054 @@ -4776,28 +4901,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
5055                                                                       cache->
5056                                                                       data);
5057                                 }
5058 -                               else if(cache &&
5059 +                               else if(cache && 
5060                                         !cache->dirty &&
5061                                         !yaffs_CheckSpaceForAllocation(in->myDev)){
5062                                         /* Drop the cache if it was a read cache item and
5063                                          * no space check has been made for it.
5064 -                                        */
5065 +                                        */ 
5066                                          cache = NULL;
5067                                 }
5068  
5069                                 if (cache) {
5070                                         yaffs_UseChunkCache(dev, cache, 1);
5071                                         cache->locked = 1;
5072 -#ifdef CONFIG_YAFFS_WINCE
5073 -                                       yfsd_UnlockYAFFS(TRUE);
5074 -#endif
5075 +
5076  
5077                                         memcpy(&cache->data[start], buffer,
5078                                                nToCopy);
5079  
5080 -#ifdef CONFIG_YAFFS_WINCE
5081 -                                       yfsd_LockYAFFS(TRUE);
5082 -#endif
5083 +
5084                                         cache->locked = 0;
5085                                         cache->nBytes = nToWriteBack;
5086  
5087 @@ -4825,15 +4946,10 @@ int yaffs_WriteDataToFile(yaffs_Object *
5088                                 yaffs_ReadChunkDataFromObject(in, chunk,
5089                                                               localBuffer);
5090  
5091 -#ifdef CONFIG_YAFFS_WINCE
5092 -                               yfsd_UnlockYAFFS(TRUE);
5093 -#endif
5094 +
5095  
5096                                 memcpy(&localBuffer[start], buffer, nToCopy);
5097  
5098 -#ifdef CONFIG_YAFFS_WINCE
5099 -                               yfsd_LockYAFFS(TRUE);
5100 -#endif
5101                                 chunkWritten =
5102                                     yaffs_WriteChunkDataToObject(in, chunk,
5103                                                                  localBuffer,
5104 @@ -4846,31 +4962,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
5105                         }
5106  
5107                 } else {
5108 -
5109 -#ifdef CONFIG_YAFFS_WINCE
5110 -                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
5111 -                        * This is because we otherwise screw up WinCE's memory mapper
5112 -                        */
5113 -                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
5114 -#ifdef CONFIG_YAFFS_WINCE
5115 -                       yfsd_UnlockYAFFS(TRUE);
5116 -#endif
5117 -                       memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
5118 -#ifdef CONFIG_YAFFS_WINCE
5119 -                       yfsd_LockYAFFS(TRUE);
5120 -#endif
5121 -                       chunkWritten =
5122 -                           yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
5123 -                                                        dev->nDataBytesPerChunk,
5124 -                                                        0);
5125 -                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
5126 -#else
5127                         /* A full chunk. Write directly from the supplied buffer. */
5128 +                       
5129 +
5130 +
5131                         chunkWritten =
5132                             yaffs_WriteChunkDataToObject(in, chunk, buffer,
5133                                                          dev->nDataBytesPerChunk,
5134                                                          0);
5135 -#endif
5136 +
5137                         /* Since we've overwritten the cached data, we better invalidate it. */
5138                         yaffs_InvalidateChunkCache(in, chunk);
5139                 }
5140 @@ -4943,9 +5043,9 @@ int yaffs_ResizeFile(yaffs_Object * in, 
5141  {
5142  
5143         int oldFileSize = in->variant.fileVariant.fileSize;
5144 -       int newSizeOfPartialChunk;
5145 +       __u32 newSizeOfPartialChunk;
5146         int newFullChunks;
5147 -
5148 +       
5149         yaffs_Device *dev = in->myDev;
5150  
5151         yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
5152 @@ -4953,23 +5053,23 @@ int yaffs_ResizeFile(yaffs_Object * in, 
5153         yaffs_FlushFilesChunkCache(in);
5154         yaffs_InvalidateWholeChunkCache(in);
5155  
5156 -       yaffs_CheckGarbageCollection(dev);
5157 +        yaffs_CheckGarbageCollection(dev);
5158  
5159 -       if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
5160 -               return yaffs_GetFileSize(in);
5161 -       }
5162 +        if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
5163 +                return YAFFS_FAIL;
5164 +        }
5165  
5166 -       if (newSize == oldFileSize) {
5167 -               return oldFileSize;
5168 -       }
5169 +        if (newSize == oldFileSize) {
5170 +                return YAFFS_OK;
5171 +        }
5172  
5173 -       if (newSize < oldFileSize) {
5174 +        if (newSize < oldFileSize) {
5175  
5176                 yaffs_PruneResizedChunks(in, newSize);
5177  
5178                 if (newSizeOfPartialChunk != 0) {
5179                         int lastChunk = 1 + newFullChunks;
5180 -
5181 +                       
5182                         __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
5183  
5184                         /* Got to read and rewrite the last chunk with its new size and zero pad */
5185 @@ -4993,19 +5093,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
5186                 in->variant.fileVariant.fileSize = newSize;
5187         }
5188  
5189 -
5190 -
5191 +               
5192 +       
5193         /* Write a new object header.
5194          * show we've shrunk the file, if need be
5195          * Do this only if the file is not in the deleted directories.
5196          */
5197 -       if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
5198 +       if (in->parent &&
5199 +           in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
5200             in->parent->objectId != YAFFS_OBJECTID_DELETED) {
5201                 yaffs_UpdateObjectHeader(in, NULL, 0,
5202                                          (newSize < oldFileSize) ? 1 : 0, 0);
5203         }
5204  
5205 -       return newSize;
5206 +       return YAFFS_OK;
5207  }
5208  
5209  loff_t yaffs_GetFileSize(yaffs_Object * obj)
5210 @@ -5058,13 +5159,13 @@ static int yaffs_DoGenericObjectDeletion
5211  
5212         if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
5213                 /* Move to the unlinked directory so we have a record that it was deleted. */
5214 -               yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
5215 +               yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
5216  
5217         }
5218  
5219         yaffs_RemoveObjectFromDirectory(in);
5220 -       yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
5221 -       in->chunkId = -1;
5222 +       yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__);
5223 +       in->hdrChunk = 0;
5224  
5225         yaffs_FreeObject(in);
5226         return YAFFS_OK;
5227 @@ -5075,62 +5176,66 @@ static int yaffs_DoGenericObjectDeletion
5228   * and the inode associated with the file.
5229   * It does not delete the links associated with the file.
5230   */
5231
5232  static int yaffs_UnlinkFile(yaffs_Object * in)
5233  {
5234  
5235         int retVal;
5236         int immediateDeletion = 0;
5237  
5238 -       if (1) {
5239  #ifdef __KERNEL__
5240 -               if (!in->myInode) {
5241 -                       immediateDeletion = 1;
5242 -
5243 -               }
5244 +       if (!in->myInode) {
5245 +               immediateDeletion = 1;
5246 +       }
5247  #else
5248 -               if (in->inUse <= 0) {
5249 -                       immediateDeletion = 1;
5250 -
5251 -               }
5252 +       if (in->inUse <= 0) {
5253 +               immediateDeletion = 1;
5254 +       }
5255  #endif
5256 -               if (immediateDeletion) {
5257 -                       retVal =
5258 -                           yaffs_ChangeObjectName(in, in->myDev->deletedDir,
5259 -                                                  "deleted", 0, 0);
5260 -                       T(YAFFS_TRACE_TRACING,
5261 -                         (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
5262 -                          in->objectId));
5263 -                       in->deleted = 1;
5264 -                       in->myDev->nDeletedFiles++;
5265 -                       if (0 && in->myDev->isYaffs2) {
5266 -                               yaffs_ResizeFile(in, 0);
5267 -                       }
5268 -                       yaffs_SoftDeleteFile(in);
5269 -               } else {
5270 -                       retVal =
5271 -                           yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
5272 -                                                  "unlinked", 0, 0);
5273 -               }
5274  
5275 +       if (immediateDeletion) {
5276 +               retVal =
5277 +                   yaffs_ChangeObjectName(in, in->myDev->deletedDir,
5278 +                                          _Y("deleted"), 0, 0);
5279 +               T(YAFFS_TRACE_TRACING,
5280 +                 (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
5281 +                  in->objectId));
5282 +               in->deleted = 1;
5283 +               in->myDev->nDeletedFiles++;
5284 +               if (1 || in->myDev->isYaffs2) {
5285 +                       yaffs_ResizeFile(in, 0);
5286 +               }
5287 +               yaffs_SoftDeleteFile(in);
5288 +       } else {
5289 +               retVal =
5290 +                   yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
5291 +                                          _Y("unlinked"), 0, 0);
5292         }
5293 +
5294 +
5295         return retVal;
5296  }
5297  
5298  int yaffs_DeleteFile(yaffs_Object * in)
5299  {
5300         int retVal = YAFFS_OK;
5301 +       int deleted = in->deleted;
5302 +       
5303 +       yaffs_ResizeFile(in,0);
5304  
5305         if (in->nDataChunks > 0) {
5306 -               /* Use soft deletion if there is data in the file */
5307 +               /* Use soft deletion if there is data in the file.
5308 +                * That won't be the case if it has been resized to zero.
5309 +                */
5310                 if (!in->unlinked) {
5311                         retVal = yaffs_UnlinkFile(in);
5312                 }
5313                 if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
5314 -                       in->deleted = 1;
5315 +                       in->deleted = deleted = 1;
5316                         in->myDev->nDeletedFiles++;
5317                         yaffs_SoftDeleteFile(in);
5318                 }
5319 -               return in->deleted ? YAFFS_OK : YAFFS_FAIL;
5320 +               return deleted ? YAFFS_OK : YAFFS_FAIL;
5321         } else {
5322                 /* The file has no data chunks so we toss it immediately */
5323                 yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
5324 @@ -5143,10 +5248,10 @@ int yaffs_DeleteFile(yaffs_Object * in)
5325  
5326  static int yaffs_DeleteDirectory(yaffs_Object * in)
5327  {
5328 -       /* First check that the directory is empty. */
5329 -       if (list_empty(&in->variant.directoryVariant.children)) {
5330 -               return yaffs_DoGenericObjectDeletion(in);
5331 -       }
5332 +        /* First check that the directory is empty. */
5333 +        if (ylist_empty(&in->variant.directoryVariant.children)) {
5334 +                return yaffs_DoGenericObjectDeletion(in);
5335 +        }
5336  
5337         return YAFFS_FAIL;
5338  
5339 @@ -5161,11 +5266,11 @@ static int yaffs_DeleteSymLink(yaffs_Obj
5340  
5341  static int yaffs_DeleteHardLink(yaffs_Object * in)
5342  {
5343 -       /* remove this hardlink from the list assocaited with the equivalent
5344 -        * object
5345 -        */
5346 -       list_del(&in->hardLinks);
5347 -       return yaffs_DoGenericObjectDeletion(in);
5348 +        /* remove this hardlink from the list assocaited with the equivalent
5349 +         * object
5350 +         */
5351 +        ylist_del_init(&in->hardLinks);
5352 +        return yaffs_DoGenericObjectDeletion(in);
5353  }
5354  
5355  static void yaffs_DestroyObject(yaffs_Object * obj)
5356 @@ -5194,12 +5299,12 @@ static void yaffs_DestroyObject(yaffs_Ob
5357  static int yaffs_UnlinkWorker(yaffs_Object * obj)
5358  {
5359  
5360 -       if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
5361 -               return yaffs_DeleteHardLink(obj);
5362 -       } else if (!list_empty(&obj->hardLinks)) {
5363 -               /* Curve ball: We're unlinking an object that has a hardlink.
5364 -                *
5365 -                * This problem arises because we are not strictly following
5366 +        if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
5367 +                return yaffs_DeleteHardLink(obj);
5368 +        } else if (!ylist_empty(&obj->hardLinks)) {
5369 +                /* Curve ball: We're unlinking an object that has a hardlink.
5370 +                 *
5371 +                 * This problem arises because we are not strictly following
5372                  * The Linux link/inode model.
5373                  *
5374                  * We can't really delete the object.
5375 @@ -5212,15 +5317,15 @@ static int yaffs_UnlinkWorker(yaffs_Obje
5376                  */
5377  
5378                 yaffs_Object *hl;
5379 -               int retVal;
5380 -               YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
5381 +                int retVal;
5382 +                YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
5383  
5384 -               hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
5385 +                hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
5386  
5387 -               list_del_init(&hl->hardLinks);
5388 -               list_del_init(&hl->siblings);
5389 +                ylist_del_init(&hl->hardLinks);
5390 +                ylist_del_init(&hl->siblings);
5391  
5392 -               yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
5393 +                yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
5394  
5395                 retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
5396  
5397 @@ -5313,7 +5418,7 @@ static void yaffs_HardlinkFixup(yaffs_De
5398  {
5399         yaffs_Object *hl;
5400         yaffs_Object *in;
5401 -
5402 +       
5403         while (hardList) {
5404                 hl = hardList;
5405                 hardList = (yaffs_Object *) (hardList->hardLinks.next);
5406 @@ -5322,18 +5427,18 @@ static void yaffs_HardlinkFixup(yaffs_De
5407                                               hl->variant.hardLinkVariant.
5408                                               equivalentObjectId);
5409  
5410 -               if (in) {
5411 -                       /* Add the hardlink pointers */
5412 -                       hl->variant.hardLinkVariant.equivalentObject = in;
5413 -                       list_add(&hl->hardLinks, &in->hardLinks);
5414 -               } else {
5415 -                       /* Todo Need to report/handle this better.
5416 -                        * Got a problem... hardlink to a non-existant object
5417 -                        */
5418 -                       hl->variant.hardLinkVariant.equivalentObject = NULL;
5419 -                       INIT_LIST_HEAD(&hl->hardLinks);
5420 +                if (in) {
5421 +                        /* Add the hardlink pointers */
5422 +                        hl->variant.hardLinkVariant.equivalentObject = in;
5423 +                        ylist_add(&hl->hardLinks, &in->hardLinks);
5424 +                } else {
5425 +                        /* Todo Need to report/handle this better.
5426 +                         * Got a problem... hardlink to a non-existant object
5427 +                         */
5428 +                        hl->variant.hardLinkVariant.equivalentObject = NULL;
5429 +                        YINIT_LIST_HEAD(&hl->hardLinks);
5430  
5431 -               }
5432 +                }
5433  
5434         }
5435  
5436 @@ -5355,6 +5460,42 @@ static int ybicmp(const void *a, const v
5437  
5438  }
5439  
5440 +
5441 +struct yaffs_ShadowFixerStruct {
5442 +       int objectId;
5443 +       int shadowedId;
5444 +       struct yaffs_ShadowFixerStruct *next;
5445 +};
5446 +
5447 +
5448 +static void yaffs_StripDeletedObjects(yaffs_Device *dev)
5449 +{
5450 +       /*
5451 +       *  Sort out state of unlinked and deleted objects after scanning.
5452 +       */
5453 +       struct ylist_head *i;
5454 +       struct ylist_head *n;
5455 +       yaffs_Object *l;
5456 +
5457 +       /* Soft delete all the unlinked files */
5458 +       ylist_for_each_safe(i, n,
5459 +               &dev->unlinkedDir->variant.directoryVariant.children) {
5460 +               if (i) {
5461 +                       l = ylist_entry(i, yaffs_Object, siblings);
5462 +                       yaffs_DestroyObject(l);
5463 +               }
5464 +       }
5465 +       
5466 +       ylist_for_each_safe(i, n,
5467 +               &dev->deletedDir->variant.directoryVariant.children) {
5468 +               if (i) {
5469 +                       l = ylist_entry(i, yaffs_Object, siblings);
5470 +                       yaffs_DestroyObject(l);
5471 +               }
5472 +       }
5473 +
5474 +}
5475 +
5476  static int yaffs_Scan(yaffs_Device * dev)
5477  {
5478         yaffs_ExtendedTags tags;
5479 @@ -5362,7 +5503,6 @@ static int yaffs_Scan(yaffs_Device * dev
5480         int blockIterator;
5481         int startIterator;
5482         int endIterator;
5483 -       int nBlocksToScan = 0;
5484         int result;
5485  
5486         int chunk;
5487 @@ -5371,27 +5511,20 @@ static int yaffs_Scan(yaffs_Device * dev
5488         yaffs_BlockState state;
5489         yaffs_Object *hardList = NULL;
5490         yaffs_BlockInfo *bi;
5491 -       int sequenceNumber;
5492 +       __u32 sequenceNumber;
5493         yaffs_ObjectHeader *oh;
5494         yaffs_Object *in;
5495         yaffs_Object *parent;
5496 -       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
5497 -
5498 +       
5499         int alloc_failed = 0;
5500 -
5501 +       
5502 +       struct yaffs_ShadowFixerStruct *shadowFixerList = NULL;
5503 +       
5504  
5505         __u8 *chunkData;
5506  
5507 -       yaffs_BlockIndex *blockIndex = NULL;
5508 -
5509 -       if (dev->isYaffs2) {
5510 -               T(YAFFS_TRACE_SCAN,
5511 -                 (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
5512 -               return YAFFS_FAIL;
5513 -       }
5514 -
5515 -       //TODO  Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
5516 -
5517 +       
5518 +       
5519         T(YAFFS_TRACE_SCAN,
5520           (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
5521            dev->internalStartBlock, dev->internalEndBlock));
5522 @@ -5400,12 +5533,6 @@ static int yaffs_Scan(yaffs_Device * dev
5523  
5524         dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
5525  
5526 -       if (dev->isYaffs2) {
5527 -               blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
5528 -               if(!blockIndex)
5529 -                       return YAFFS_FAIL;
5530 -       }
5531 -
5532         /* Scan all the blocks to determine their state */
5533         for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
5534                 bi = yaffs_GetBlockInfo(dev, blk);
5535 @@ -5430,70 +5557,21 @@ static int yaffs_Scan(yaffs_Device * dev
5536                           (TSTR("Block empty " TENDSTR)));
5537                         dev->nErasedBlocks++;
5538                         dev->nFreeChunks += dev->nChunksPerBlock;
5539 -               } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
5540 -
5541 -                       /* Determine the highest sequence number */
5542 -                       if (dev->isYaffs2 &&
5543 -                           sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5544 -                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
5545 -
5546 -                               blockIndex[nBlocksToScan].seq = sequenceNumber;
5547 -                               blockIndex[nBlocksToScan].block = blk;
5548 -
5549 -                               nBlocksToScan++;
5550 -
5551 -                               if (sequenceNumber >= dev->sequenceNumber) {
5552 -                                       dev->sequenceNumber = sequenceNumber;
5553 -                               }
5554 -                       } else if (dev->isYaffs2) {
5555 -                               /* TODO: Nasty sequence number! */
5556 -                               T(YAFFS_TRACE_SCAN,
5557 -                                 (TSTR
5558 -                                  ("Block scanning block %d has bad sequence number %d"
5559 -                                   TENDSTR), blk, sequenceNumber));
5560 -
5561 -                       }
5562 -               }
5563 +               } 
5564         }
5565  
5566 -       /* Sort the blocks
5567 -        * Dungy old bubble sort for now...
5568 -        */
5569 -       if (dev->isYaffs2) {
5570 -               yaffs_BlockIndex temp;
5571 -               int i;
5572 -               int j;
5573 -
5574 -               for (i = 0; i < nBlocksToScan; i++)
5575 -                       for (j = i + 1; j < nBlocksToScan; j++)
5576 -                               if (blockIndex[i].seq > blockIndex[j].seq) {
5577 -                                       temp = blockIndex[j];
5578 -                                       blockIndex[j] = blockIndex[i];
5579 -                                       blockIndex[i] = temp;
5580 -                               }
5581 -       }
5582 -
5583 -       /* Now scan the blocks looking at the data. */
5584 -       if (dev->isYaffs2) {
5585 -               startIterator = 0;
5586 -               endIterator = nBlocksToScan - 1;
5587 -               T(YAFFS_TRACE_SCAN_DEBUG,
5588 -                 (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
5589 -       } else {
5590 -               startIterator = dev->internalStartBlock;
5591 -               endIterator = dev->internalEndBlock;
5592 -       }
5593 +       startIterator = dev->internalStartBlock;
5594 +       endIterator = dev->internalEndBlock;
5595  
5596         /* For each block.... */
5597         for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
5598              blockIterator++) {
5599 +               
5600 +               YYIELD();
5601  
5602 -               if (dev->isYaffs2) {
5603 -                       /* get the block to scan in the correct order */
5604 -                       blk = blockIndex[blockIterator].block;
5605 -               } else {
5606 -                       blk = blockIterator;
5607 -               }
5608 +               YYIELD();
5609 +               
5610 +               blk = blockIterator;
5611  
5612                 bi = yaffs_GetBlockInfo(dev, blk);
5613                 state = bi->blockState;
5614 @@ -5511,7 +5589,7 @@ static int yaffs_Scan(yaffs_Device * dev
5615  
5616                         /* Let's have a good look at this chunk... */
5617  
5618 -                       if (!dev->isYaffs2 && tags.chunkDeleted) {
5619 +                       if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {
5620                                 /* YAFFS1 only...
5621                                  * A deleted chunk
5622                                  */
5623 @@ -5520,7 +5598,7 @@ static int yaffs_Scan(yaffs_Device * dev
5624                                 /*T((" %d %d deleted\n",blk,c)); */
5625                         } else if (!tags.chunkUsed) {
5626                                 /* An unassigned chunk in the block
5627 -                                * This means that either the block is empty or
5628 +                                * This means that either the block is empty or 
5629                                  * this is the one being allocated from
5630                                  */
5631  
5632 @@ -5537,21 +5615,9 @@ static int yaffs_Scan(yaffs_Device * dev
5633                                         state = YAFFS_BLOCK_STATE_ALLOCATING;
5634                                         dev->allocationBlock = blk;
5635                                         dev->allocationPage = c;
5636 -                                       dev->allocationBlockFinder = blk;
5637 +                                       dev->allocationBlockFinder = blk;       
5638                                         /* Set it to here to encourage the allocator to go forth from here. */
5639 -
5640 -                                       /* Yaffs2 sanity check:
5641 -                                        * This should be the one with the highest sequence number
5642 -                                        */
5643 -                                       if (dev->isYaffs2
5644 -                                           && (dev->sequenceNumber !=
5645 -                                               bi->sequenceNumber)) {
5646 -                                               T(YAFFS_TRACE_ALWAYS,
5647 -                                                 (TSTR
5648 -                                                  ("yaffs: Allocation block %d was not highest sequence id:"
5649 -                                                   " block seq = %d, dev seq = %d"
5650 -                                                   TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
5651 -                                       }
5652 +                                       
5653                                 }
5654  
5655                                 dev->nFreeChunks += (dev->nChunksPerBlock - c);
5656 @@ -5569,7 +5635,7 @@ static int yaffs_Scan(yaffs_Device * dev
5657                                 /* PutChunkIntoFile checks for a clash (two data chunks with
5658                                  * the same chunkId).
5659                                  */
5660 -
5661 +                                
5662                                 if(!in)
5663                                         alloc_failed = 1;
5664  
5665 @@ -5577,11 +5643,11 @@ static int yaffs_Scan(yaffs_Device * dev
5666                                         if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1))
5667                                                 alloc_failed = 1;
5668                                 }
5669 -
5670 +                               
5671                                 endpos =
5672                                     (tags.chunkId - 1) * dev->nDataBytesPerChunk +
5673                                     tags.byteCount;
5674 -                               if (in &&
5675 +                               if (in && 
5676                                     in->variantType == YAFFS_OBJECT_TYPE_FILE
5677                                     && in->variant.fileVariant.scannedFileSize <
5678                                     endpos) {
5679 @@ -5613,7 +5679,7 @@ static int yaffs_Scan(yaffs_Device * dev
5680                                                               tags.objectId);
5681                                 if (in && in->variantType != oh->type) {
5682                                         /* This should not happen, but somehow
5683 -                                        * Wev'e ended up with an objectId that has been reused but not yet
5684 +                                        * Wev'e ended up with an objectId that has been reused but not yet 
5685                                          * deleted, and worse still it has changed type. Delete the old object.
5686                                          */
5687  
5688 @@ -5629,12 +5695,18 @@ static int yaffs_Scan(yaffs_Device * dev
5689  
5690                                 if(!in)
5691                                         alloc_failed = 1;
5692 -
5693 +                                       
5694                                 if (in && oh->shadowsObject > 0) {
5695 -                                       yaffs_HandleShadowedObject(dev,
5696 -                                                                  oh->
5697 -                                                                  shadowsObject,
5698 -                                                                  0);
5699 +                               
5700 +                                       struct yaffs_ShadowFixerStruct *fixer;
5701 +                                       fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct));
5702 +                                       if(fixer){
5703 +                                               fixer-> next = shadowFixerList;
5704 +                                               shadowFixerList = fixer;
5705 +                                               fixer->objectId = tags.objectId;
5706 +                                               fixer->shadowedId = oh->shadowsObject;
5707 +                                       }
5708 +                                       
5709                                 }
5710  
5711                                 if (in && in->valid) {
5712 @@ -5643,12 +5715,10 @@ static int yaffs_Scan(yaffs_Device * dev
5713                                         unsigned existingSerial = in->serial;
5714                                         unsigned newSerial = tags.serialNumber;
5715  
5716 -                                       if (dev->isYaffs2 ||
5717 -                                           ((existingSerial + 1) & 3) ==
5718 -                                           newSerial) {
5719 +                                       if (((existingSerial + 1) & 3) == newSerial) {
5720                                                 /* Use new one - destroy the exisiting one */
5721                                                 yaffs_DeleteChunk(dev,
5722 -                                                                 in->chunkId,
5723 +                                                                 in->hdrChunk,
5724                                                                   1, __LINE__);
5725                                                 in->valid = 0;
5726                                         } else {
5727 @@ -5681,7 +5751,8 @@ static int yaffs_Scan(yaffs_Device * dev
5728                                         in->yst_ctime = oh->yst_ctime;
5729                                         in->yst_rdev = oh->yst_rdev;
5730  #endif
5731 -                                       in->chunkId = chunk;
5732 +                                       in->hdrChunk = chunk;
5733 +                                       in->serial = tags.serialNumber;
5734  
5735                                 } else if (in && !in->valid) {
5736                                         /* we need to load this info */
5737 @@ -5705,7 +5776,8 @@ static int yaffs_Scan(yaffs_Device * dev
5738                                         in->yst_ctime = oh->yst_ctime;
5739                                         in->yst_rdev = oh->yst_rdev;
5740  #endif
5741 -                                       in->chunkId = chunk;
5742 +                                       in->hdrChunk = chunk;
5743 +                                       in->serial = tags.serialNumber;
5744  
5745                                         yaffs_SetObjectName(in, oh->name);
5746                                         in->dirty = 0;
5747 @@ -5720,13 +5792,13 @@ static int yaffs_Scan(yaffs_Device * dev
5748                                              YAFFS_OBJECT_TYPE_DIRECTORY);
5749                                         if (parent->variantType ==
5750                                             YAFFS_OBJECT_TYPE_UNKNOWN) {
5751 -                                               /* Set up as a directory */
5752 -                                               parent->variantType =
5753 -                                                   YAFFS_OBJECT_TYPE_DIRECTORY;
5754 -                                               INIT_LIST_HEAD(&parent->variant.
5755 -                                                              directoryVariant.
5756 -                                                              children);
5757 -                                       } else if (parent->variantType !=
5758 +                                                /* Set up as a directory */
5759 +                                                parent->variantType =
5760 +                                                    YAFFS_OBJECT_TYPE_DIRECTORY;
5761 +                                                YINIT_LIST_HEAD(&parent->variant.
5762 +                                                               directoryVariant.
5763 +                                                               children);
5764 +                                        } else if (parent->variantType !=
5765                                                    YAFFS_OBJECT_TYPE_DIRECTORY)
5766                                         {
5767                                                 /* Hoosterman, another problem....
5768 @@ -5735,8 +5807,7 @@ static int yaffs_Scan(yaffs_Device * dev
5769  
5770                                                 T(YAFFS_TRACE_ERROR,
5771                                                   (TSTR
5772 -                                                  ("yaffs tragedy: attempting to use non-directory as"
5773 -                                                   " a directory in scan. Put in lost+found."
5774 +                                                  ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
5775                                                     TENDSTR)));
5776                                                 parent = dev->lostNFoundDir;
5777                                         }
5778 @@ -5752,23 +5823,14 @@ static int yaffs_Scan(yaffs_Device * dev
5779                                          * Since we might scan a hardlink before its equivalent object is scanned
5780                                          * we put them all in a list.
5781                                          * After scanning is complete, we should have all the objects, so we run through this
5782 -                                        * list and fix up all the chains.
5783 +                                        * list and fix up all the chains.              
5784                                          */
5785  
5786                                         switch (in->variantType) {
5787 -                                       case YAFFS_OBJECT_TYPE_UNKNOWN:
5788 +                                       case YAFFS_OBJECT_TYPE_UNKNOWN: 
5789                                                 /* Todo got a problem */
5790                                                 break;
5791                                         case YAFFS_OBJECT_TYPE_FILE:
5792 -                                               if (dev->isYaffs2
5793 -                                                   && oh->isShrink) {
5794 -                                                       /* Prune back the shrunken chunks */
5795 -                                                       yaffs_PruneResizedChunks
5796 -                                                           (in, oh->fileSize);
5797 -                                                       /* Mark the block as having a shrinkHeader */
5798 -                                                       bi->hasShrinkHeader = 1;
5799 -                                               }
5800 -
5801                                                 if (dev->useHeaderFileSize)
5802  
5803                                                         in->variant.fileVariant.
5804 @@ -5778,20 +5840,20 @@ static int yaffs_Scan(yaffs_Device * dev
5805                                                 break;
5806                                         case YAFFS_OBJECT_TYPE_HARDLINK:
5807                                                 in->variant.hardLinkVariant.
5808 -                                                   equivalentObjectId =
5809 -                                                   oh->equivalentObjectId;
5810 -                                               in->hardLinks.next =
5811 -                                                   (struct list_head *)
5812 -                                                   hardList;
5813 -                                               hardList = in;
5814 -                                               break;
5815 +                                                    equivalentObjectId =
5816 +                                                    oh->equivalentObjectId;
5817 +                                                in->hardLinks.next =
5818 +                                                    (struct ylist_head *)
5819 +                                                    hardList;
5820 +                                                hardList = in;
5821 +                                                break;
5822                                         case YAFFS_OBJECT_TYPE_DIRECTORY:
5823                                                 /* Do nothing */
5824                                                 break;
5825                                         case YAFFS_OBJECT_TYPE_SPECIAL:
5826                                                 /* Do nothing */
5827                                                 break;
5828 -                                       case YAFFS_OBJECT_TYPE_SYMLINK:
5829 +                                       case YAFFS_OBJECT_TYPE_SYMLINK: 
5830                                                 in->variant.symLinkVariant.alias =
5831                                                     yaffs_CloneString(oh->alias);
5832                                                 if(!in->variant.symLinkVariant.alias)
5833 @@ -5799,10 +5861,12 @@ static int yaffs_Scan(yaffs_Device * dev
5834                                                 break;
5835                                         }
5836  
5837 -                                       if (parent == dev->deletedDir) {
5838 +/*
5839 +                                       if (parent == dev->deletedDir) {
5840                                                 yaffs_DestroyObject(in);
5841                                                 bi->hasShrinkHeader = 1;
5842                                         }
5843 +*/
5844                                 }
5845                         }
5846                 }
5847 @@ -5823,35 +5887,36 @@ static int yaffs_Scan(yaffs_Device * dev
5848  
5849         }
5850  
5851 -       if (blockIndex) {
5852 -               YFREE(blockIndex);
5853 -       }
5854 -
5855 -
5856 +       
5857         /* Ok, we've done all the scanning.
5858          * Fix up the hard link chains.
5859 -        * We should now have scanned all the objects, now it's time to add these
5860 +        * We should now have scanned all the objects, now it's time to add these 
5861          * hardlinks.
5862          */
5863  
5864         yaffs_HardlinkFixup(dev,hardList);
5865 -
5866 -       /* Handle the unlinked files. Since they were left in an unlinked state we should
5867 -        * just delete them.
5868 -        */
5869 +       
5870 +       /* Fix up any shadowed objects */
5871         {
5872 -               struct list_head *i;
5873 -               struct list_head *n;
5874 -
5875 -               yaffs_Object *l;
5876 -               /* Soft delete all the unlinked files */
5877 -               list_for_each_safe(i, n,
5878 -                                  &dev->unlinkedDir->variant.directoryVariant.
5879 -                                  children) {
5880 -                       if (i) {
5881 -                               l = list_entry(i, yaffs_Object, siblings);
5882 -                               yaffs_DestroyObject(l);
5883 +               struct yaffs_ShadowFixerStruct *fixer;
5884 +               yaffs_Object *obj;
5885 +               
5886 +               while(shadowFixerList){
5887 +                       fixer = shadowFixerList;
5888 +                       shadowFixerList = fixer->next;
5889 +                       /* Complete the rename transaction by deleting the shadowed object
5890 +                        * then setting the object header to unshadowed.
5891 +                        */
5892 +                       obj = yaffs_FindObjectByNumber(dev,fixer->shadowedId);
5893 +                       if(obj)
5894 +                               yaffs_DestroyObject(obj);
5895 +       
5896 +                       obj = yaffs_FindObjectByNumber(dev,fixer->objectId);
5897 +                       if(obj){
5898 +                               yaffs_UpdateObjectHeader(obj,NULL,1,0,0);
5899                         }
5900 +                       
5901 +                       YFREE(fixer);
5902                 }
5903         }
5904  
5905 @@ -5860,9 +5925,9 @@ static int yaffs_Scan(yaffs_Device * dev
5906         if(alloc_failed){
5907                 return YAFFS_FAIL;
5908         }
5909 -
5910 +       
5911         T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
5912 -
5913 +       
5914  
5915         return YAFFS_OK;
5916  }
5917 @@ -5871,25 +5936,27 @@ static void yaffs_CheckObjectDetailsLoad
5918  {
5919         __u8 *chunkData;
5920         yaffs_ObjectHeader *oh;
5921 -       yaffs_Device *dev = in->myDev;
5922 +       yaffs_Device *dev;
5923         yaffs_ExtendedTags tags;
5924         int result;
5925         int alloc_failed = 0;
5926  
5927         if(!in)
5928                 return;
5929 -
5930 +               
5931 +       dev = in->myDev;
5932 +               
5933  #if 0
5934         T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
5935                 in->objectId,
5936                 in->lazyLoaded ? "not yet" : "already"));
5937  #endif
5938  
5939 -       if(in->lazyLoaded){
5940 +       if(in->lazyLoaded && in->hdrChunk > 0){
5941                 in->lazyLoaded = 0;
5942                 chunkData = yaffs_GetTempBuffer(dev, __LINE__);
5943  
5944 -               result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
5945 +               result = yaffs_ReadChunkWithTagsFromNAND(dev,in->hdrChunk,chunkData,&tags);
5946                 oh = (yaffs_ObjectHeader *) chunkData;
5947  
5948                 in->yst_mode = oh->yst_mode;
5949 @@ -5907,17 +5974,17 @@ static void yaffs_CheckObjectDetailsLoad
5950                 in->yst_mtime = oh->yst_mtime;
5951                 in->yst_ctime = oh->yst_ctime;
5952                 in->yst_rdev = oh->yst_rdev;
5953 -
5954 +               
5955  #endif
5956                 yaffs_SetObjectName(in, oh->name);
5957 -
5958 +               
5959                 if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){
5960                          in->variant.symLinkVariant.alias =
5961                                                     yaffs_CloneString(oh->alias);
5962                         if(!in->variant.symLinkVariant.alias)
5963                                 alloc_failed = 1; /* Not returned to caller */
5964                 }
5965 -
5966 +                                                   
5967                 yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
5968         }
5969  }
5970 @@ -5938,20 +6005,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5971         yaffs_BlockState state;
5972         yaffs_Object *hardList = NULL;
5973         yaffs_BlockInfo *bi;
5974 -       int sequenceNumber;
5975 +       __u32 sequenceNumber;
5976         yaffs_ObjectHeader *oh;
5977         yaffs_Object *in;
5978         yaffs_Object *parent;
5979         int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
5980         int itsUnlinked;
5981         __u8 *chunkData;
5982 -
5983 +       
5984         int fileSize;
5985         int isShrink;
5986         int foundChunksInBlock;
5987         int equivalentObjectId;
5988         int alloc_failed = 0;
5989 -
5990 +       
5991  
5992         yaffs_BlockIndex *blockIndex = NULL;
5993         int altBlockIndex = 0;
5994 @@ -5971,20 +6038,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5995         dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
5996  
5997         blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
5998 -
5999 +       
6000         if(!blockIndex) {
6001                 blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
6002                 altBlockIndex = 1;
6003         }
6004 -
6005 +       
6006         if(!blockIndex) {
6007                 T(YAFFS_TRACE_SCAN,
6008                   (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
6009                 return YAFFS_FAIL;
6010         }
6011 -
6012 +       
6013         dev->blocksInCheckpoint = 0;
6014 -
6015 +       
6016         chunkData = yaffs_GetTempBuffer(dev, __LINE__);
6017  
6018         /* Scan all the blocks to determine their state */
6019 @@ -6001,15 +6068,15 @@ static int yaffs_ScanBackwards(yaffs_Dev
6020  
6021                 if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
6022                         bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
6023 -
6024 +                       
6025                 T(YAFFS_TRACE_SCAN_DEBUG,
6026                   (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
6027                    state, sequenceNumber));
6028  
6029 -
6030 +               
6031                 if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
6032                         dev->blocksInCheckpoint++;
6033 -
6034 +                       
6035                 } else if (state == YAFFS_BLOCK_STATE_DEAD) {
6036                         T(YAFFS_TRACE_BAD_BLOCKS,
6037                           (TSTR("block %d is bad" TENDSTR), blk));
6038 @@ -6021,8 +6088,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6039                 } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
6040  
6041                         /* Determine the highest sequence number */
6042 -                       if (dev->isYaffs2 &&
6043 -                           sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
6044 +                       if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
6045                             sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
6046  
6047                                 blockIndex[nBlocksToScan].seq = sequenceNumber;
6048 @@ -6033,7 +6099,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6049                                 if (sequenceNumber >= dev->sequenceNumber) {
6050                                         dev->sequenceNumber = sequenceNumber;
6051                                 }
6052 -                       } else if (dev->isYaffs2) {
6053 +                       } else {
6054                                 /* TODO: Nasty sequence number! */
6055                                 T(YAFFS_TRACE_SCAN,
6056                                   (TSTR
6057 @@ -6053,12 +6119,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
6058  
6059         /* Sort the blocks */
6060  #ifndef CONFIG_YAFFS_USE_OWN_SORT
6061 -       yaffs_qsort(blockIndex, nBlocksToScan,
6062 -               sizeof(yaffs_BlockIndex), ybicmp);
6063 +       {
6064 +               /* Use qsort now. */
6065 +               yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
6066 +       }
6067  #else
6068         {
6069                 /* Dungy old bubble sort... */
6070 -
6071 +               
6072                 yaffs_BlockIndex temp;
6073                 int i;
6074                 int j;
6075 @@ -6094,22 +6162,22 @@ static int yaffs_ScanBackwards(yaffs_Dev
6076                 blk = blockIndex[blockIterator].block;
6077  
6078                 bi = yaffs_GetBlockInfo(dev, blk);
6079 -
6080 -
6081 +               
6082 +               
6083                 state = bi->blockState;
6084  
6085                 deleted = 0;
6086  
6087                 /* For each chunk in each block that needs scanning.... */
6088                 foundChunksInBlock = 0;
6089 -               for (c = dev->nChunksPerBlock - 1;
6090 +               for (c = dev->nChunksPerBlock - 1; 
6091                      !alloc_failed && c >= 0 &&
6092                      (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
6093                       state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
6094 -                       /* Scan backwards...
6095 +                       /* Scan backwards... 
6096                          * Read the tags and decide what to do
6097                          */
6098 -
6099 +                       
6100                         chunk = blk * dev->nChunksPerBlock + c;
6101  
6102                         result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
6103 @@ -6123,14 +6191,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
6104                                  * it is a chunk that was skipped due to failing the erased
6105                                  * check. Just skip it so that it can be deleted.
6106                                  * But, more typically, We get here when this is an unallocated
6107 -                                * chunk and his means that either the block is empty or
6108 +                                * chunk and his means that either the block is empty or 
6109                                  * this is the one being allocated from
6110                                  */
6111  
6112                                 if(foundChunksInBlock)
6113                                 {
6114                                         /* This is a chunk that was skipped due to failing the erased check */
6115 -
6116 +                                       
6117                                 } else if (c == 0) {
6118                                         /* We're looking at the first chunk in the block so the block is unused */
6119                                         state = YAFFS_BLOCK_STATE_EMPTY;
6120 @@ -6140,7 +6208,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6121                                             state == YAFFS_BLOCK_STATE_ALLOCATING) {
6122                                                 if(dev->sequenceNumber == bi->sequenceNumber) {
6123                                                         /* this is the block being allocated from */
6124 -
6125 +                                               
6126                                                         T(YAFFS_TRACE_SCAN,
6127                                                           (TSTR
6128                                                            (" Allocating from %d %d"
6129 @@ -6149,34 +6217,41 @@ static int yaffs_ScanBackwards(yaffs_Dev
6130                                                         state = YAFFS_BLOCK_STATE_ALLOCATING;
6131                                                         dev->allocationBlock = blk;
6132                                                         dev->allocationPage = c;
6133 -                                                       dev->allocationBlockFinder = blk;
6134 +                                                       dev->allocationBlockFinder = blk;       
6135                                                 }
6136                                                 else {
6137                                                         /* This is a partially written block that is not
6138                                                          * the current allocation block. This block must have
6139                                                          * had a write failure, so set up for retirement.
6140                                                          */
6141 -
6142 -                                                        bi->needsRetiring = 1;
6143 +                                                 
6144 +                                                        /* bi->needsRetiring = 1; ??? TODO */
6145                                                          bi->gcPrioritise = 1;
6146 -
6147 +                                                                                                        
6148                                                          T(YAFFS_TRACE_ALWAYS,
6149 -                                                        (TSTR("Partially written block %d being set for retirement" TENDSTR),
6150 +                                                        (TSTR("Partially written block %d detected" TENDSTR),
6151                                                          blk));
6152                                                 }
6153  
6154                                         }
6155 -
6156 +                                        
6157                                 }
6158  
6159                                 dev->nFreeChunks++;
6160 +                               
6161 +                       } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){
6162 +                               T(YAFFS_TRACE_SCAN,
6163 +                                 (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR),
6164 +                                 blk, c));
6165  
6166 -                       } else if (tags.chunkId > 0) {
6167 +                                 dev->nFreeChunks++;
6168 +
6169 +                       }else if (tags.chunkId > 0) {
6170                                 /* chunkId > 0 so it is a data chunk... */
6171                                 unsigned int endpos;
6172                                 __u32 chunkBase =
6173                                     (tags.chunkId - 1) * dev->nDataBytesPerChunk;
6174 -
6175 +                                                               
6176                                 foundChunksInBlock = 1;
6177  
6178  
6179 @@ -6191,7 +6266,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6180                                         /* Out of memory */
6181                                         alloc_failed = 1;
6182                                 }
6183 -
6184 +                               
6185                                 if (in &&
6186                                     in->variantType == YAFFS_OBJECT_TYPE_FILE
6187                                     && chunkBase <
6188 @@ -6202,14 +6277,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
6189                                                 alloc_failed = 1;
6190                                         }
6191  
6192 -                                       /* File size is calculated by looking at the data chunks if we have not
6193 +                                       /* File size is calculated by looking at the data chunks if we have not 
6194                                          * seen an object header yet. Stop this practice once we find an object header.
6195                                          */
6196                                         endpos =
6197                                             (tags.chunkId -
6198                                              1) * dev->nDataBytesPerChunk +
6199                                             tags.byteCount;
6200 -
6201 +                                           
6202                                         if (!in->valid &&       /* have not got an object header yet */
6203                                             in->variant.fileVariant.
6204                                             scannedFileSize < endpos) {
6205 @@ -6255,7 +6330,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6206                                     ) {
6207  
6208                                         /* If we don't have  valid info then we need to read the chunk
6209 -                                        * TODO In future we can probably defer reading the chunk and
6210 +                                        * TODO In future we can probably defer reading the chunk and 
6211                                          * living with invalid data until needed.
6212                                          */
6213  
6214 @@ -6265,6 +6340,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
6215                                                                         NULL);
6216  
6217                                         oh = (yaffs_ObjectHeader *) chunkData;
6218 +                                       
6219 +                                       if(dev->inbandTags){
6220 +                                               /* Fix up the header if they got corrupted by inband tags */
6221 +                                               oh->shadowsObject = oh->inbandShadowsObject;
6222 +                                               oh->isShrink = oh->inbandIsShrink;
6223 +                                       }
6224  
6225                                         if (!in)
6226                                                 in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
6227 @@ -6275,20 +6356,19 @@ static int yaffs_ScanBackwards(yaffs_Dev
6228                                         /* TODO Hoosterman we have a problem! */
6229                                         T(YAFFS_TRACE_ERROR,
6230                                           (TSTR
6231 -                                          ("yaffs tragedy: Could not make object for object  %d  "
6232 -                                           "at chunk %d during scan"
6233 +                                          ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"
6234                                             TENDSTR), tags.objectId, chunk));
6235  
6236                                 }
6237  
6238                                 if (in->valid) {
6239                                         /* We have already filled this one.
6240 -                                        * We have a duplicate that will be discarded, but
6241 +                                        * We have a duplicate that will be discarded, but 
6242                                          * we first have to suck out resize info if it is a file.
6243                                          */
6244  
6245 -                                       if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
6246 -                                            ((oh &&
6247 +                                       if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && 
6248 +                                            ((oh && 
6249                                                oh-> type == YAFFS_OBJECT_TYPE_FILE)||
6250                                               (tags.extraHeaderInfoAvailable  &&
6251                                                tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
6252 @@ -6300,7 +6380,9 @@ static int yaffs_ScanBackwards(yaffs_Dev
6253                                                     (oh) ? oh->
6254                                                     parentObjectId : tags.
6255                                                     extraParentObjectId;
6256 -                                               unsigned isShrink =
6257 +                                               
6258 +                                               
6259 +                                               isShrink =
6260                                                     (oh) ? oh->isShrink : tags.
6261                                                     extraIsShrinkHeader;
6262  
6263 @@ -6339,7 +6421,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6264                                      YAFFS_OBJECTID_LOSTNFOUND)) {
6265                                         /* We only load some info, don't fiddle with directory structure */
6266                                         in->valid = 1;
6267 -
6268 +                                       
6269                                         if(oh) {
6270                                                 in->variantType = oh->type;
6271  
6272 @@ -6358,20 +6440,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
6273                                                 in->yst_mtime = oh->yst_mtime;
6274                                                 in->yst_ctime = oh->yst_ctime;
6275                                                 in->yst_rdev = oh->yst_rdev;
6276 -
6277 +               
6278  #endif
6279                                         } else {
6280                                                 in->variantType = tags.extraObjectType;
6281                                                 in->lazyLoaded = 1;
6282                                         }
6283  
6284 -                                       in->chunkId = chunk;
6285 +                                       in->hdrChunk = chunk;
6286  
6287                                 } else if (!in->valid) {
6288                                         /* we need to load this info */
6289  
6290                                         in->valid = 1;
6291 -                                       in->chunkId = chunk;
6292 +                                       in->hdrChunk = chunk;
6293  
6294                                         if(oh) {
6295                                                 in->variantType = oh->type;
6296 @@ -6393,12 +6475,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
6297                                                 in->yst_rdev = oh->yst_rdev;
6298  #endif
6299  
6300 -                                               if (oh->shadowsObject > 0)
6301 +                                               if (oh->shadowsObject > 0) 
6302                                                         yaffs_HandleShadowedObject(dev,
6303                                                                            oh->
6304                                                                            shadowsObject,
6305                                                                            1);
6306 -
6307 +                                       
6308  
6309                                                 yaffs_SetObjectName(in, oh->name);
6310                                                 parent =
6311 @@ -6431,13 +6513,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
6312  
6313                                         if (parent->variantType ==
6314                                             YAFFS_OBJECT_TYPE_UNKNOWN) {
6315 -                                               /* Set up as a directory */
6316 -                                               parent->variantType =
6317 -                                                   YAFFS_OBJECT_TYPE_DIRECTORY;
6318 -                                               INIT_LIST_HEAD(&parent->variant.
6319 -                                                              directoryVariant.
6320 -                                                              children);
6321 -                                       } else if (parent->variantType !=
6322 +                                                /* Set up as a directory */
6323 +                                                parent->variantType =
6324 +                                                    YAFFS_OBJECT_TYPE_DIRECTORY;
6325 +                                                YINIT_LIST_HEAD(&parent->variant.
6326 +                                                               directoryVariant.
6327 +                                                               children);
6328 +                                        } else if (parent->variantType !=
6329                                                    YAFFS_OBJECT_TYPE_DIRECTORY)
6330                                         {
6331                                                 /* Hoosterman, another problem....
6332 @@ -6446,8 +6528,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6333  
6334                                                 T(YAFFS_TRACE_ERROR,
6335                                                   (TSTR
6336 -                                                  ("yaffs tragedy: attempting to use non-directory as"
6337 -                                                   " a directory in scan. Put in lost+found."
6338 +                                                  ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
6339                                                     TENDSTR)));
6340                                                 parent = dev->lostNFoundDir;
6341                                         }
6342 @@ -6466,11 +6547,11 @@ static int yaffs_ScanBackwards(yaffs_Dev
6343                                          * Since we might scan a hardlink before its equivalent object is scanned
6344                                          * we put them all in a list.
6345                                          * After scanning is complete, we should have all the objects, so we run
6346 -                                        * through this list and fix up all the chains.
6347 +                                        * through this list and fix up all the chains.              
6348                                          */
6349  
6350                                         switch (in->variantType) {
6351 -                                       case YAFFS_OBJECT_TYPE_UNKNOWN:
6352 +                                       case YAFFS_OBJECT_TYPE_UNKNOWN: 
6353                                                 /* Todo got a problem */
6354                                                 break;
6355                                         case YAFFS_OBJECT_TYPE_FILE:
6356 @@ -6479,7 +6560,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6357                                                     scannedFileSize < fileSize) {
6358                                                         /* This covers the case where the file size is greater
6359                                                          * than where the data is
6360 -                                                        * This will happen if the file is resized to be larger
6361 +                                                        * This will happen if the file is resized to be larger 
6362                                                          * than its current data extents.
6363                                                          */
6364                                                         in->variant.fileVariant.fileSize = fileSize;
6365 @@ -6495,13 +6576,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
6366                                                 break;
6367                                         case YAFFS_OBJECT_TYPE_HARDLINK:
6368                                                 if(!itsUnlinked) {
6369 -                                                 in->variant.hardLinkVariant.equivalentObjectId =
6370 -                                                   equivalentObjectId;
6371 -                                                 in->hardLinks.next =
6372 -                                                   (struct list_head *) hardList;
6373 -                                                 hardList = in;
6374 -                                               }
6375 -                                               break;
6376 +                                                  in->variant.hardLinkVariant.equivalentObjectId =
6377 +                                                    equivalentObjectId;
6378 +                                                  in->hardLinks.next =
6379 +                                                    (struct ylist_head *) hardList;
6380 +                                                  hardList = in;
6381 +                                                }
6382 +                                                break;
6383                                         case YAFFS_OBJECT_TYPE_DIRECTORY:
6384                                                 /* Do nothing */
6385                                                 break;
6386 @@ -6520,7 +6601,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
6387                                         }
6388  
6389                                 }
6390 -
6391 +                               
6392                         }
6393  
6394                 } /* End of scanning for each chunk */
6395 @@ -6541,72 +6622,128 @@ static int yaffs_ScanBackwards(yaffs_Dev
6396  
6397         }
6398  
6399 -       if (altBlockIndex)
6400 +       if (altBlockIndex) 
6401                 YFREE_ALT(blockIndex);
6402         else
6403                 YFREE(blockIndex);
6404 -
6405 +       
6406         /* Ok, we've done all the scanning.
6407          * Fix up the hard link chains.
6408 -        * We should now have scanned all the objects, now it's time to add these
6409 +        * We should now have scanned all the objects, now it's time to add these 
6410          * hardlinks.
6411          */
6412         yaffs_HardlinkFixup(dev,hardList);
6413 +       
6414  
6415 +       yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
6416 +       
6417 +       if(alloc_failed){
6418 +               return YAFFS_FAIL;
6419 +       }
6420  
6421 -       /*
6422 -       *  Sort out state of unlinked and deleted objects.
6423 -       */
6424 -       {
6425 -               struct list_head *i;
6426 -               struct list_head *n;
6427 +       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
6428  
6429 -               yaffs_Object *l;
6430 +       return YAFFS_OK;
6431 +}
6432  
6433 -               /* Soft delete all the unlinked files */
6434 -               list_for_each_safe(i, n,
6435 -                                  &dev->unlinkedDir->variant.directoryVariant.
6436 -                                  children) {
6437 -                       if (i) {
6438 -                               l = list_entry(i, yaffs_Object, siblings);
6439 -                               yaffs_DestroyObject(l);
6440 -                       }
6441 -               }
6442 +/*------------------------------  Directory Functions ----------------------------- */
6443  
6444 -               /* Soft delete all the deletedDir files */
6445 -               list_for_each_safe(i, n,
6446 -                                  &dev->deletedDir->variant.directoryVariant.
6447 -                                  children) {
6448 -                       if (i) {
6449 -                               l = list_entry(i, yaffs_Object, siblings);
6450 -                               yaffs_DestroyObject(l);
6451 +static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj)
6452 +{
6453 +        struct ylist_head *lh;
6454 +        yaffs_Object *listObj;
6455 +        
6456 +        int count = 0;
6457  
6458 -                       }
6459 -               }
6460 +       if(!obj){
6461 +               T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR)));
6462 +               YBUG();
6463         }
6464  
6465 -       yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
6466 +        if(yaffs_SkipVerification(obj->myDev))
6467 +                return;
6468  
6469 -       if(alloc_failed){
6470 -               return YAFFS_FAIL;
6471 +       if(!obj->parent){
6472 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR)));
6473 +               YBUG();
6474 +       }
6475 +               
6476 +       if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
6477 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR)));
6478 +               YBUG();
6479 +       }
6480 +       
6481 +        /* Iterate through the objects in each hash entry */
6482 +         
6483 +        ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) {
6484 +               if (lh) {
6485 +                        listObj = ylist_entry(lh, yaffs_Object, siblings);
6486 +                       yaffs_VerifyObject(listObj);
6487 +                       if(obj == listObj)
6488 +                               count ++;
6489 +                }
6490 +        }
6491 +        
6492 +        if(count != 1){
6493 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR),count));
6494 +               YBUG();
6495         }
6496  
6497 -       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
6498 +}
6499  
6500 -       return YAFFS_OK;
6501 +static void yaffs_VerifyDirectory(yaffs_Object *directory)
6502 +{
6503 +
6504 +        struct ylist_head *lh;
6505 +        yaffs_Object *listObj;
6506 +        
6507 +       if(!directory)
6508 +               YBUG();
6509 +
6510 +        if(yaffs_SkipFullVerification(directory->myDev))
6511 +                return;
6512 +
6513 +               
6514 +       if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
6515 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR),directory->variantType));
6516 +               YBUG();
6517 +       }
6518 +       
6519 +        /* Iterate through the objects in each hash entry */
6520 +         
6521 +        ylist_for_each(lh, &directory->variant.directoryVariant.children) {
6522 +               if (lh) {
6523 +                        listObj = ylist_entry(lh, yaffs_Object, siblings);
6524 +                       if(listObj->parent != directory){
6525 +                               T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR),listObj->parent));
6526 +                               YBUG();
6527 +                       }
6528 +                       yaffs_VerifyObjectInDirectory(listObj);
6529 +                }
6530 +        }
6531 +        
6532  }
6533  
6534 -/*------------------------------  Directory Functions ----------------------------- */
6535  
6536  static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
6537  {
6538         yaffs_Device *dev = obj->myDev;
6539 +       yaffs_Object *parent;
6540 +       
6541 +        yaffs_VerifyObjectInDirectory(obj);
6542 +       parent = obj->parent;
6543 +       
6544 +       yaffs_VerifyDirectory(parent);
6545 +
6546 +        if(dev && dev->removeObjectCallback)
6547 +                dev->removeObjectCallback(obj);
6548 +
6549 +           
6550 +        ylist_del_init(&obj->siblings);
6551 +        obj->parent = NULL;
6552  
6553 -       if(dev && dev->removeObjectCallback)
6554 -               dev->removeObjectCallback(obj);
6555 +       yaffs_VerifyDirectory(parent);
6556  
6557 -       list_del_init(&obj->siblings);
6558 -       obj->parent = NULL;
6559  }
6560  
6561  
6562 @@ -6629,35 +6766,46 @@ static void yaffs_AddObjectToDirectory(y
6563                 YBUG();
6564         }
6565  
6566 -       if (obj->siblings.prev == NULL) {
6567 -               /* Not initialised */
6568 -               INIT_LIST_HEAD(&obj->siblings);
6569 -
6570 -       } else if (!list_empty(&obj->siblings)) {
6571 -               /* If it is holed up somewhere else, un hook it */
6572 -               yaffs_RemoveObjectFromDirectory(obj);
6573 -       }
6574 -       /* Now add it */
6575 -       list_add(&obj->siblings, &directory->variant.directoryVariant.children);
6576 -       obj->parent = directory;
6577 +        if (obj->siblings.prev == NULL) {
6578 +                /* Not initialised */
6579 +                YBUG();
6580 +
6581 +        } else if (ylist_empty(&obj->siblings)) {
6582 +               YBUG();
6583 +        } 
6584 +
6585  
6586 -       if (directory == obj->myDev->unlinkedDir
6587 +       yaffs_VerifyDirectory(directory);
6588 +
6589 +       yaffs_RemoveObjectFromDirectory(obj);
6590 +        
6591 +        
6592 +        /* Now add it */
6593 +        ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
6594 +        obj->parent = directory;
6595 +
6596 +        if (directory == obj->myDev->unlinkedDir
6597             || directory == obj->myDev->deletedDir) {
6598                 obj->unlinked = 1;
6599                 obj->myDev->nUnlinkedFiles++;
6600                 obj->renameAllowed = 0;
6601         }
6602 +
6603 +       yaffs_VerifyDirectory(directory);
6604 +        yaffs_VerifyObjectInDirectory(obj);
6605 +
6606 +
6607  }
6608  
6609  yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
6610                                      const YCHAR * name)
6611  {
6612 -       int sum;
6613 +        int sum;
6614  
6615 -       struct list_head *i;
6616 -       YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
6617 +        struct ylist_head *i;
6618 +        YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
6619  
6620 -       yaffs_Object *l;
6621 +        yaffs_Object *l;
6622  
6623         if (!name) {
6624                 return NULL;
6625 @@ -6677,22 +6825,24 @@ yaffs_Object *yaffs_FindObjectByName(yaf
6626                 YBUG();
6627         }
6628  
6629 -       sum = yaffs_CalcNameSum(name);
6630 +        sum = yaffs_CalcNameSum(name);
6631  
6632 -       list_for_each(i, &directory->variant.directoryVariant.children) {
6633 -               if (i) {
6634 -                       l = list_entry(i, yaffs_Object, siblings);
6635 -
6636 -                       yaffs_CheckObjectDetailsLoaded(l);
6637 +        ylist_for_each(i, &directory->variant.directoryVariant.children) {
6638 +                if (i) {
6639 +                        l = ylist_entry(i, yaffs_Object, siblings);
6640 +                        
6641 +                        if(l->parent != directory)
6642 +                               YBUG();
6643 +                        
6644 +                        yaffs_CheckObjectDetailsLoaded(l);
6645  
6646                         /* Special case for lost-n-found */
6647                         if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
6648                                 if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
6649                                         return l;
6650                                 }
6651 -                       } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
6652 -                       {
6653 -                               /* LostnFound cunk called Objxxx
6654 +                       } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0){
6655 +                               /* LostnFound chunk called Objxxx
6656                                  * Do a real check
6657                                  */
6658                                 yaffs_GetObjectName(l, buffer,
6659 @@ -6711,12 +6861,12 @@ yaffs_Object *yaffs_FindObjectByName(yaf
6660  
6661  #if 0
6662  int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
6663 -                                  int (*fn) (yaffs_Object *))
6664 +                                   int (*fn) (yaffs_Object *))
6665  {
6666 -       struct list_head *i;
6667 -       yaffs_Object *l;
6668 +        struct ylist_head *i;
6669 +        yaffs_Object *l;
6670  
6671 -       if (!theDir) {
6672 +        if (!theDir) {
6673                 T(YAFFS_TRACE_ALWAYS,
6674                   (TSTR
6675                    ("tragedy: yaffs_FindObjectByName: null pointer directory"
6676 @@ -6727,15 +6877,15 @@ int yaffs_ApplyToDirectoryChildren(yaffs
6677                 T(YAFFS_TRACE_ALWAYS,
6678                   (TSTR
6679                    ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
6680 -               YBUG();
6681 -       }
6682 +                YBUG();
6683 +        }
6684  
6685 -       list_for_each(i, &theDir->variant.directoryVariant.children) {
6686 -               if (i) {
6687 -                       l = list_entry(i, yaffs_Object, siblings);
6688 -                       if (l && !fn(l)) {
6689 -                               return YAFFS_FAIL;
6690 -                       }
6691 +        ylist_for_each(i, &theDir->variant.directoryVariant.children) {
6692 +                if (i) {
6693 +                        l = ylist_entry(i, yaffs_Object, siblings);
6694 +                        if (l && !fn(l)) {
6695 +                                return YAFFS_FAIL;
6696 +                        }
6697                 }
6698         }
6699  
6700 @@ -6762,16 +6912,25 @@ yaffs_Object *yaffs_GetEquivalentObject(
6701  int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
6702  {
6703         memset(name, 0, buffSize * sizeof(YCHAR));
6704 -
6705 +       
6706         yaffs_CheckObjectDetailsLoaded(obj);
6707  
6708         if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
6709                 yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
6710 -       } else if (obj->chunkId <= 0) {
6711 +       } else if (obj->hdrChunk <= 0) {
6712                 YCHAR locName[20];
6713 +               YCHAR numString[20];
6714 +               YCHAR *x = &numString[19];
6715 +               unsigned v = obj->objectId;
6716 +               numString[19] = 0;
6717 +               while(v>0){
6718 +                       x--;
6719 +                       *x = '0' + (v % 10);
6720 +                       v /= 10;
6721 +               }
6722                 /* make up a name */
6723 -               yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
6724 -                             obj->objectId);
6725 +               yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX);
6726 +               yaffs_strcat(locName,x);
6727                 yaffs_strncpy(name, locName, buffSize - 1);
6728  
6729         }
6730 @@ -6788,9 +6947,9 @@ int yaffs_GetObjectName(yaffs_Object * o
6731  
6732                 memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
6733  
6734 -               if (obj->chunkId >= 0) {
6735 +               if (obj->hdrChunk > 0) {
6736                         result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
6737 -                                                       obj->chunkId, buffer,
6738 +                                                       obj->hdrChunk, buffer,
6739                                                         NULL);
6740                 }
6741                 yaffs_strncpy(name, oh->name, buffSize - 1);
6742 @@ -6820,16 +6979,16 @@ int yaffs_GetObjectFileLength(yaffs_Obje
6743  
6744  int yaffs_GetObjectLinkCount(yaffs_Object * obj)
6745  {
6746 -       int count = 0;
6747 -       struct list_head *i;
6748 +        int count = 0;
6749 +        struct ylist_head *i;
6750  
6751 -       if (!obj->unlinked) {
6752 -               count++;        /* the object itself */
6753 -       }
6754 -       list_for_each(i, &obj->hardLinks) {
6755 -               count++;        /* add the hard links; */
6756 -       }
6757 -       return count;
6758 +        if (!obj->unlinked) {
6759 +                count++;        /* the object itself */
6760 +        }
6761 +        ylist_for_each(i, &obj->hardLinks) {
6762 +                count++;        /* add the hard links; */
6763 +        }
6764 +        return count;
6765  
6766  }
6767  
6768 @@ -6951,7 +7110,7 @@ int yaffs_DumpObject(yaffs_Object * obj)
6769            ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
6770             " chunk %d type %d size %d\n"
6771             TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
6772 -          obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
6773 +          obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk,
6774            yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
6775  
6776         return YAFFS_OK;
6777 @@ -6994,13 +7153,13 @@ static int yaffs_CheckDevFunctions(const
6778  static int yaffs_CreateInitialDirectories(yaffs_Device *dev)
6779  {
6780         /* Initialise the unlinked, deleted, root and lost and found directories */
6781 -
6782 +       
6783         dev->lostNFoundDir = dev->rootDir =  NULL;
6784         dev->unlinkedDir = dev->deletedDir = NULL;
6785  
6786         dev->unlinkedDir =
6787             yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
6788 -
6789 +       
6790         dev->deletedDir =
6791             yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
6792  
6793 @@ -7010,12 +7169,12 @@ static int yaffs_CreateInitialDirectorie
6794         dev->lostNFoundDir =
6795             yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
6796                                       YAFFS_LOSTNFOUND_MODE | S_IFDIR);
6797 -
6798 +       
6799         if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){
6800                 yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
6801                 return YAFFS_OK;
6802         }
6803 -
6804 +       
6805         return YAFFS_FAIL;
6806  }
6807  
6808 @@ -7039,6 +7198,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
6809         dev->blockOffset = 0;
6810         dev->chunkOffset = 0;
6811         dev->nFreeChunks = 0;
6812 +       
6813 +       dev->gcBlock = -1;
6814  
6815         if (dev->startBlock == 0) {
6816                 dev->internalStartBlock = dev->startBlock + 1;
6817 @@ -7049,18 +7210,19 @@ int yaffs_GutsInitialise(yaffs_Device * 
6818  
6819         /* Check geometry parameters. */
6820  
6821 -       if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
6822 -           (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
6823 -            dev->nChunksPerBlock < 2 ||
6824 -            dev->nReservedBlocks < 2 ||
6825 -            dev->internalStartBlock <= 0 ||
6826 -            dev->internalEndBlock <= 0 ||
6827 +       if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || 
6828 +           (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || 
6829 +           (dev->inbandTags && !dev->isYaffs2 ) ||
6830 +            dev->nChunksPerBlock < 2 || 
6831 +            dev->nReservedBlocks < 2 || 
6832 +            dev->internalStartBlock <= 0 || 
6833 +            dev->internalEndBlock <= 0 || 
6834              dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)      // otherwise it is too small
6835             ) {
6836                 T(YAFFS_TRACE_ALWAYS,
6837                   (TSTR
6838 -                  ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
6839 -                   TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
6840 +                  ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
6841 +                   TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
6842                 return YAFFS_FAIL;
6843         }
6844  
6845 @@ -7069,6 +7231,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
6846                   (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
6847                 return YAFFS_FAIL;
6848         }
6849 +       
6850 +       /* Sort out space for inband tags, if required */
6851 +       if(dev->inbandTags)
6852 +               dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
6853 +       else 
6854 +               dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
6855  
6856         /* Got the right mix of functions? */
6857         if (!yaffs_CheckDevFunctions(dev)) {
6858 @@ -7097,41 +7265,28 @@ int yaffs_GutsInitialise(yaffs_Device * 
6859  
6860         dev->isMounted = 1;
6861  
6862 -
6863 -
6864         /* OK now calculate a few things for the device */
6865 -
6866 +       
6867         /*
6868 -        *  Calculate all the chunk size manipulation numbers:
6869 +        *  Calculate all the chunk size manipulation numbers:   
6870          */
6871 -        /* Start off assuming it is a power of 2 */
6872 -        dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
6873 -        dev->chunkMask = (1<<dev->chunkShift) - 1;
6874 -
6875 -        if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
6876 -               /* Yes it is a power of 2, disable crumbs */
6877 -               dev->crumbMask = 0;
6878 -               dev->crumbShift = 0;
6879 -               dev->crumbsPerChunk = 0;
6880 -        } else {
6881 -               /* Not a power of 2, use crumbs instead */
6882 -               dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
6883 -               dev->crumbMask = (1<<dev->crumbShift)-1;
6884 -               dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
6885 -               dev->chunkShift = 0;
6886 -               dev->chunkMask = 0;
6887 -       }
6888 -
6889 -
6890 +       x = dev->nDataBytesPerChunk;
6891 +       /* We always use dev->chunkShift and dev->chunkDiv */
6892 +       dev->chunkShift = Shifts(x);
6893 +       x >>= dev->chunkShift;
6894 +       dev->chunkDiv = x;
6895 +       /* We only use chunk mask if chunkDiv is 1 */
6896 +       dev->chunkMask = (1<<dev->chunkShift) - 1;
6897 +               
6898         /*
6899          * Calculate chunkGroupBits.
6900          * We need to find the next power of 2 > than internalEndBlock
6901          */
6902  
6903         x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
6904 -
6905 +       
6906         bits = ShiftsGE(x);
6907 -
6908 +       
6909         /* Set up tnode width if wide tnodes are enabled. */
6910         if(!dev->wideTnodesDisabled){
6911                 /* bits must be even so that we end up with 32-bit words */
6912 @@ -7144,20 +7299,20 @@ int yaffs_GutsInitialise(yaffs_Device * 
6913         }
6914         else
6915                 dev->tnodeWidth = 16;
6916 -
6917
6918         dev->tnodeMask = (1<<dev->tnodeWidth)-1;
6919 -
6920 +               
6921         /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
6922          * so if the bitwidth of the
6923          * chunk range we're using is greater than 16 we need
6924          * to figure out chunk shift and chunkGroupSize
6925          */
6926 -
6927 +                
6928         if (bits <= dev->tnodeWidth)
6929                 dev->chunkGroupBits = 0;
6930         else
6931                 dev->chunkGroupBits = bits - dev->tnodeWidth;
6932 -
6933 +               
6934  
6935         dev->chunkGroupSize = 1 << dev->chunkGroupBits;
6936  
6937 @@ -7195,40 +7350,42 @@ int yaffs_GutsInitialise(yaffs_Device * 
6938         /* Initialise temporary buffers and caches. */
6939         if(!yaffs_InitialiseTempBuffers(dev))
6940                 init_failed = 1;
6941 -
6942 +       
6943         dev->srCache = NULL;
6944         dev->gcCleanupList = NULL;
6945 -
6946 -
6947 +       
6948 +       
6949         if (!init_failed &&
6950             dev->nShortOpCaches > 0) {
6951                 int i;
6952 -               __u8 *buf;
6953 +               void *buf;
6954                 int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
6955  
6956                 if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
6957                         dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
6958                 }
6959  
6960 -               buf = dev->srCache =  YMALLOC(srCacheBytes);
6961 -
6962 +               dev->srCache =  YMALLOC(srCacheBytes);
6963 +               
6964 +               buf = (__u8 *) dev->srCache;
6965 +                   
6966                 if(dev->srCache)
6967                         memset(dev->srCache,0,srCacheBytes);
6968 -
6969 +                  
6970                 for (i = 0; i < dev->nShortOpCaches && buf; i++) {
6971                         dev->srCache[i].object = NULL;
6972                         dev->srCache[i].lastUse = 0;
6973                         dev->srCache[i].dirty = 0;
6974 -                       dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
6975 +                       dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
6976                 }
6977                 if(!buf)
6978                         init_failed = 1;
6979 -
6980 +                       
6981                 dev->srLastUse = 0;
6982         }
6983  
6984         dev->cacheHits = 0;
6985 -
6986 +       
6987         if(!init_failed){
6988                 dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
6989                 if(!dev->gcCleanupList)
6990 @@ -7240,7 +7397,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
6991         }
6992         if(!init_failed && !yaffs_InitialiseBlocks(dev))
6993                 init_failed = 1;
6994 -
6995 +               
6996         yaffs_InitialiseTnodes(dev);
6997         yaffs_InitialiseObjects(dev);
6998  
6999 @@ -7252,18 +7409,19 @@ int yaffs_GutsInitialise(yaffs_Device * 
7000                 /* Now scan the flash. */
7001                 if (dev->isYaffs2) {
7002                         if(yaffs_CheckpointRestore(dev)) {
7003 +                               yaffs_CheckObjectDetailsLoaded(dev->rootDir);
7004                                 T(YAFFS_TRACE_ALWAYS,
7005                                   (TSTR("yaffs: restored from checkpoint" TENDSTR)));
7006                         } else {
7007  
7008 -                               /* Clean up the mess caused by an aborted checkpoint load
7009 -                                * and scan backwards.
7010 +                               /* Clean up the mess caused by an aborted checkpoint load 
7011 +                                * and scan backwards. 
7012                                  */
7013                                 yaffs_DeinitialiseBlocks(dev);
7014                                 yaffs_DeinitialiseTnodes(dev);
7015                                 yaffs_DeinitialiseObjects(dev);
7016 -
7017 -
7018 +                               
7019 +                       
7020                                 dev->nErasedBlocks = 0;
7021                                 dev->nFreeChunks = 0;
7022                                 dev->allocationBlock = -1;
7023 @@ -7275,7 +7433,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
7024  
7025                                 if(!init_failed && !yaffs_InitialiseBlocks(dev))
7026                                         init_failed = 1;
7027 -
7028 +                                       
7029                                 yaffs_InitialiseTnodes(dev);
7030                                 yaffs_InitialiseObjects(dev);
7031  
7032 @@ -7288,8 +7446,10 @@ int yaffs_GutsInitialise(yaffs_Device * 
7033                 }else
7034                         if(!yaffs_Scan(dev))
7035                                 init_failed = 1;
7036 -       }
7037  
7038 +               yaffs_StripDeletedObjects(dev);
7039 +       }
7040 +               
7041         if(init_failed){
7042                 /* Clean up the mess */
7043                 T(YAFFS_TRACE_TRACING,
7044 @@ -7310,7 +7470,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
7045  
7046         yaffs_VerifyFreeChunks(dev);
7047         yaffs_VerifyBlocks(dev);
7048 -
7049 +       
7050  
7051         T(YAFFS_TRACE_TRACING,
7052           (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
7053 @@ -7345,7 +7505,11 @@ void yaffs_Deinitialise(yaffs_Device * d
7054                         YFREE(dev->tempBuffer[i].buffer);
7055                 }
7056  
7057 +
7058                 dev->isMounted = 0;
7059 +               
7060 +               if(dev->deinitialiseNAND)
7061 +                       dev->deinitialiseNAND(dev);
7062         }
7063  
7064  }
7065 @@ -7394,7 +7558,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
7066  #endif
7067  
7068         nFree += dev->nDeletedFiles;
7069 -
7070 +       
7071         /* Now count the number of dirty chunks in the cache and subtract those */
7072  
7073         {
7074 @@ -7408,12 +7572,12 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
7075         nFree -= nDirtyCacheChunks;
7076  
7077         nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
7078 -
7079 +       
7080         /* Now we figure out how much to reserve for the checkpoint and report that... */
7081 -       blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
7082 +       blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
7083         if(blocksForCheckpoint < 0)
7084                 blocksForCheckpoint = 0;
7085 -
7086 +               
7087         nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
7088  
7089         if (nFree < 0)
7090 @@ -7429,10 +7593,10 @@ static void yaffs_VerifyFreeChunks(yaffs
7091  {
7092         int counted;
7093         int difference;
7094 -
7095 +       
7096         if(yaffs_SkipVerification(dev))
7097                 return;
7098 -
7099 +       
7100         counted = yaffs_CountFreeChunks(dev);
7101  
7102         difference = dev->nFreeChunks - counted;
7103 @@ -7448,22 +7612,25 @@ static void yaffs_VerifyFreeChunks(yaffs
7104  /*---------------------------------------- YAFFS test code ----------------------*/
7105  
7106  #define yaffs_CheckStruct(structure,syze, name) \
7107 +       do { \
7108             if(sizeof(structure) != syze) \
7109                { \
7110                  T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
7111                  name,syze,sizeof(structure))); \
7112                  return YAFFS_FAIL; \
7113 -               }
7114 +               } \
7115 +       } while(0)
7116  
7117  static int yaffs_CheckStructures(void)
7118  {
7119 -/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
7120 -/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
7121 -/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
7122 +/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */
7123 +/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */
7124 +/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */
7125  #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
7126 -       yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
7127 +        yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
7128 +#endif
7129 +#ifndef CONFIG_YAFFS_WINCE
7130 +               yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
7131  #endif
7132 -           yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
7133 -
7134             return YAFFS_OK;
7135  }
7136 --- a/fs/yaffs2/yaffs_mtdif1.c
7137 +++ b/fs/yaffs2/yaffs_mtdif1.c
7138 @@ -34,9 +34,9 @@
7139  #include "linux/mtd/mtd.h"
7140  
7141  /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
7142 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7143 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7144  
7145 -const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $";
7146 +const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.8 2008-07-23 03:35:12 charles Exp $";
7147  
7148  #ifndef CONFIG_YAFFS_9BYTE_TAGS
7149  # define YTAG1_SIZE 8
7150 @@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
7151         ops.datbuf = data;
7152         ops.oobbuf = (__u8 *)&pt1;
7153  
7154 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
7155 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,20))
7156         /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
7157          * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
7158          */
7159 @@ -288,7 +288,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaf
7160         int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
7161         int retval;
7162  
7163 -       yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
7164 +       yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
7165  
7166         retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
7167         return (retval) ? YAFFS_FAIL : YAFFS_OK;
7168 @@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(stru
7169   * Always returns YAFFS_OK.
7170   */
7171  int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7172 -       yaffs_BlockState * pState, int *pSequenceNumber)
7173 +       yaffs_BlockState * pState, __u32 *pSequenceNumber)
7174  {
7175         struct mtd_info * mtd = dev->genericDevice;
7176         int chunkNo = blockNo * dev->nChunksPerBlock;
7177 +       loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
7178         yaffs_ExtendedTags etags;
7179         int state = YAFFS_BLOCK_STATE_DEAD;
7180         int seqnum = 0;
7181 @@ -340,11 +341,16 @@ int nandmtd1_QueryNANDBlock(struct yaffs
7182         }
7183  
7184         retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
7185 +       etags.blockBad = (mtd->block_isbad)(mtd, addr);
7186         if (etags.blockBad) {
7187                 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
7188 -                       "block %d is marked bad", blockNo);
7189 +                       "block %d is marked bad\n", blockNo);
7190                 state = YAFFS_BLOCK_STATE_DEAD;
7191         }
7192 +       else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
7193 +               /* bad tags, need to look more closely */
7194 +               state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
7195 +       }
7196         else if (etags.chunkUsed) {
7197                 state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
7198                 seqnum = etags.sequenceNumber;
7199 @@ -360,4 +366,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs
7200         return YAFFS_OK;
7201  }
7202  
7203 -#endif /*KERNEL_VERSION*/
7204 +#endif /*MTD_VERSION*/
7205 --- a/fs/yaffs2/yaffs_mtdif2.c
7206 +++ b/fs/yaffs2/yaffs_mtdif2.c
7207 @@ -14,7 +14,7 @@
7208  /* mtd interface for YAFFS2 */
7209  
7210  const char *yaffs_mtdif2_c_version =
7211 -    "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $";
7212 +    "$Id: yaffs_mtdif2.c,v 1.22 2008-11-02 22:47:13 charles Exp $";
7213  
7214  #include "yportenv.h"
7215  
7216 @@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version =
7217  
7218  #include "yaffs_packedtags2.h"
7219  
7220 +/* NB For use with inband tags....
7221 + * We assume that the data buffer is of size totalBytersPerChunk so that we can also
7222 + * use it to load the tags.
7223 + */
7224  int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
7225                                       const __u8 * data,
7226                                       const yaffs_ExtendedTags * tags)
7227  {
7228         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7229 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7230 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7231         struct mtd_oob_ops ops;
7232  #else
7233         size_t dummy;
7234  #endif
7235         int retval = 0;
7236  
7237 -       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
7238 +       loff_t addr;
7239  
7240         yaffs_PackedTags2 pt;
7241  
7242 @@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
7243           (TSTR
7244            ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
7245             TENDSTR), chunkInNAND, data, tags));
7246 +           
7247  
7248 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7249 -       if (tags)
7250 -               yaffs_PackTags2(&pt, tags);
7251 +       addr  = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
7252 +       
7253 +       /* For yaffs2 writing there must be both data and tags.
7254 +        * If we're using inband tags, then the tags are stuffed into
7255 +        * the end of the data buffer.
7256 +        */
7257 +       if(!data || !tags)
7258 +               BUG();  
7259 +       else if(dev->inbandTags){
7260 +               yaffs_PackedTags2TagsPart *pt2tp;
7261 +               pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
7262 +               yaffs_PackTags2TagsPart(pt2tp,tags);
7263 +       }
7264         else
7265 -               BUG(); /* both tags and data should always be present */
7266 -
7267 -       if (data) {
7268 -               ops.mode = MTD_OOB_AUTO;
7269 -               ops.ooblen = sizeof(pt);
7270 -               ops.len = dev->nDataBytesPerChunk;
7271 -               ops.ooboffs = 0;
7272 -               ops.datbuf = (__u8 *)data;
7273 -               ops.oobbuf = (void *)&pt;
7274 -               retval = mtd->write_oob(mtd, addr, &ops);
7275 -       } else
7276 -               BUG(); /* both tags and data should always be present */
7277 -#else
7278 -       if (tags) {
7279                 yaffs_PackTags2(&pt, tags);
7280 -       }
7281 +       
7282 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7283 +       ops.mode = MTD_OOB_AUTO;
7284 +       ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
7285 +       ops.len = dev->totalBytesPerChunk;
7286 +       ops.ooboffs = 0;
7287 +       ops.datbuf = (__u8 *)data;
7288 +       ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
7289 +       retval = mtd->write_oob(mtd, addr, &ops);
7290  
7291 -       if (data && tags) {
7292 -               if (dev->useNANDECC)
7293 -                       retval =
7294 -                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
7295 -                                          &dummy, data, (__u8 *) & pt, NULL);
7296 -               else
7297 -                       retval =
7298 -                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
7299 -                                          &dummy, data, (__u8 *) & pt, NULL);
7300 +#else
7301 +       if (!dev->inbandTags) {
7302 +               retval =
7303 +                   mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
7304 +                                  &dummy, data, (__u8 *) & pt, NULL);
7305         } else {
7306 -               if (data)
7307 -                       retval =
7308 -                           mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
7309 -                                      data);
7310 -               if (tags)
7311 -                       retval =
7312 -                           mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
7313 -                                          (__u8 *) & pt);
7314 -
7315 +               retval =
7316 +                   mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
7317 +                              data);
7318         }
7319  #endif
7320  
7321 @@ -101,13 +100,14 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
7322                                        __u8 * data, yaffs_ExtendedTags * tags)
7323  {
7324         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7325 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7326 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7327         struct mtd_oob_ops ops;
7328  #endif
7329         size_t dummy;
7330         int retval = 0;
7331 +       int localData = 0;
7332  
7333 -       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
7334 +       loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
7335  
7336         yaffs_PackedTags2 pt;
7337  
7338 @@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
7339           (TSTR
7340            ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
7341             TENDSTR), chunkInNAND, data, tags));
7342 +           
7343 +       if(dev->inbandTags){
7344 +               
7345 +               if(!data) {
7346 +                       localData = 1;
7347 +                       data = yaffs_GetTempBuffer(dev,__LINE__);
7348 +               }
7349 +               
7350 +
7351 +       }
7352 +
7353  
7354  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7355 -       if (data && !tags)
7356 -               retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
7357 +       if (dev->inbandTags || (data && !tags))
7358 +               retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
7359                                 &dummy, data);
7360         else if (tags) {
7361                 ops.mode = MTD_OOB_AUTO;
7362 @@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
7363                 retval = mtd->read_oob(mtd, addr, &ops);
7364         }
7365  #else
7366 -       if (data && tags) {
7367 -               if (dev->useNANDECC) {
7368 -                       retval =
7369 -                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
7370 -                                         &dummy, data, dev->spareBuffer,
7371 -                                         NULL);
7372 -               } else {
7373 -                       retval =
7374 -                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
7375 +       if (!dev->inbandTags && data && tags) {
7376 +
7377 +               retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
7378                                           &dummy, data, dev->spareBuffer,
7379                                           NULL);
7380 -               }
7381         } else {
7382                 if (data)
7383                         retval =
7384                             mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
7385                                       data);
7386 -               if (tags)
7387 +               if (!dev->inbandTags && tags)
7388                         retval =
7389                             mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
7390                                           dev->spareBuffer);
7391         }
7392  #endif
7393  
7394 -       memcpy(&pt, dev->spareBuffer, sizeof(pt));
7395  
7396 -       if (tags)
7397 -               yaffs_UnpackTags2(tags, &pt);
7398 +       if(dev->inbandTags){
7399 +               if(tags){
7400 +                       yaffs_PackedTags2TagsPart * pt2tp;
7401 +                       pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];    
7402 +                       yaffs_UnpackTags2TagsPart(tags,pt2tp);
7403 +               }
7404 +       }
7405 +       else {
7406 +               if (tags){
7407 +                       memcpy(&pt, dev->spareBuffer, sizeof(pt));
7408 +                       yaffs_UnpackTags2(tags, &pt);
7409 +               }
7410 +       }
7411  
7412 +       if(localData)
7413 +               yaffs_ReleaseTempBuffer(dev,data,__LINE__);
7414 +       
7415         if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
7416 -               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
7417 -
7418 +               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;             
7419         if (retval == 0)
7420                 return YAFFS_OK;
7421         else
7422 @@ -178,7 +194,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
7423         retval =
7424             mtd->block_markbad(mtd,
7425                                blockNo * dev->nChunksPerBlock *
7426 -                              dev->nDataBytesPerChunk);
7427 +                              dev->totalBytesPerChunk);
7428  
7429         if (retval == 0)
7430                 return YAFFS_OK;
7431 @@ -188,7 +204,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
7432  }
7433  
7434  int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7435 -                           yaffs_BlockState * state, int *sequenceNumber)
7436 +                           yaffs_BlockState * state, __u32 *sequenceNumber)
7437  {
7438         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7439         int retval;
7440 @@ -198,7 +214,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs
7441         retval =
7442             mtd->block_isbad(mtd,
7443                              blockNo * dev->nChunksPerBlock *
7444 -                            dev->nDataBytesPerChunk);
7445 +                            dev->totalBytesPerChunk);
7446  
7447         if (retval) {
7448                 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
7449 --- a/fs/yaffs2/yaffs_guts.h
7450 +++ b/fs/yaffs2/yaffs_guts.h
7451 @@ -1,5 +1,5 @@
7452  /*
7453 - * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
7454 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
7455   *
7456   * Copyright (C) 2002-2007 Aleph One Ltd.
7457   *   for Toby Churchill Ltd and Brightstar Engineering
7458 @@ -22,11 +22,11 @@
7459  #define YAFFS_OK       1
7460  #define YAFFS_FAIL  0
7461  
7462 -/* Give us a  Y=0x59,
7463 - * Give us an A=0x41,
7464 - * Give us an FF=0xFF
7465 +/* Give us a  Y=0x59, 
7466 + * Give us an A=0x41, 
7467 + * Give us an FF=0xFF 
7468   * Give us an S=0x53
7469 - * And what have we got...
7470 + * And what have we got... 
7471   */
7472  #define YAFFS_MAGIC                    0x5941FF53
7473  
7474 @@ -90,7 +90,7 @@
7475  
7476  #define YAFFS_MAX_SHORT_OP_CACHES      20
7477  
7478 -#define YAFFS_N_TEMP_BUFFERS           4
7479 +#define YAFFS_N_TEMP_BUFFERS           6
7480  
7481  /* We limit the number attempts at sucessfully saving a chunk of data.
7482   * Small-page devices have 32 pages per block; large-page devices have 64.
7483 @@ -102,7 +102,7 @@
7484   * The range is limited slightly to help distinguish bad numbers from good.
7485   * This also allows us to perhaps in the future use special numbers for
7486   * special purposes.
7487 - * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
7488 + * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, 
7489   * and is a larger number than the lifetime of a 2GB device.
7490   */
7491  #define YAFFS_LOWEST_SEQUENCE_NUMBER   0x00001000
7492 @@ -132,12 +132,12 @@ typedef struct {
7493  
7494  #ifndef CONFIG_YAFFS_NO_YAFFS1
7495  typedef struct {
7496 -       unsigned chunkId:20;
7497 -       unsigned serialNumber:2;
7498 -       unsigned byteCount:10;
7499 -       unsigned objectId:18;
7500 -       unsigned ecc:12;
7501 -       unsigned unusedStuff:2;
7502 +        unsigned chunkId:20;
7503 +        unsigned serialNumber:2;
7504 +        unsigned byteCountLSB:10;
7505 +        unsigned objectId:18;
7506 +        unsigned ecc:12;
7507 +        unsigned byteCountMSB:2;
7508  
7509  } yaffs_Tags;
7510  
7511 @@ -178,7 +178,7 @@ typedef struct {
7512  
7513         /* The following stuff only has meaning when we read */
7514         yaffs_ECCResult eccResult;
7515 -       unsigned blockBad;
7516 +       unsigned blockBad;      
7517  
7518         /* YAFFS 1 stuff */
7519         unsigned chunkDeleted;  /* The chunk is marked deleted */
7520 @@ -244,29 +244,29 @@ typedef enum {
7521         /* This block is empty */
7522  
7523         YAFFS_BLOCK_STATE_ALLOCATING,
7524 -       /* This block is partially allocated.
7525 +       /* This block is partially allocated. 
7526          * At least one page holds valid data.
7527          * This is the one currently being used for page
7528          * allocation. Should never be more than one of these
7529          */
7530  
7531 -       YAFFS_BLOCK_STATE_FULL,
7532 +       YAFFS_BLOCK_STATE_FULL, 
7533         /* All the pages in this block have been allocated.
7534          */
7535  
7536         YAFFS_BLOCK_STATE_DIRTY,
7537 -       /* All pages have been allocated and deleted.
7538 +       /* All pages have been allocated and deleted. 
7539          * Erase me, reuse me.
7540          */
7541  
7542 -       YAFFS_BLOCK_STATE_CHECKPOINT,
7543 +       YAFFS_BLOCK_STATE_CHECKPOINT,   
7544         /* This block is assigned to holding checkpoint data.
7545          */
7546  
7547 -       YAFFS_BLOCK_STATE_COLLECTING,
7548 +       YAFFS_BLOCK_STATE_COLLECTING,   
7549         /* This block is being garbage collected */
7550  
7551 -       YAFFS_BLOCK_STATE_DEAD
7552 +       YAFFS_BLOCK_STATE_DEAD  
7553         /* This block has failed and is not in use */
7554  } yaffs_BlockState;
7555  
7556 @@ -277,11 +277,11 @@ typedef struct {
7557  
7558         int softDeletions:10;   /* number of soft deleted pages */
7559         int pagesInUse:10;      /* number of pages in use */
7560 -       yaffs_BlockState blockState:4;  /* One of the above block states */
7561 +       unsigned blockState:4;  /* One of the above block states. NB use unsigned because enum is sometimes an int */
7562         __u32 needsRetiring:1;  /* Data has failed on this block, need to get valid data off */
7563                                 /* and retire the block. */
7564         __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
7565 -       __u32 gcPrioritise: 1;  /* An ECC check or blank check has failed on this block.
7566 +       __u32 gcPrioritise: 1;  /* An ECC check or blank check has failed on this block. 
7567                                    It should be prioritised for GC */
7568          __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
7569  
7570 @@ -300,11 +300,11 @@ typedef struct {
7571  
7572         /* Apply to everything  */
7573         int parentObjectId;
7574 -       __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
7575 -       YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
7576 +        __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
7577 +        YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
7578  
7579 -       /* Thes following apply to directories, files, symlinks - not hard links */
7580 -       __u32 yst_mode;         /* protection */
7581 +        /* The following apply to directories, files, symlinks - not hard links */
7582 +        __u32 yst_mode;         /* protection */
7583  
7584  #ifdef CONFIG_YAFFS_WINCE
7585         __u32 notForWinCE[5];
7586 @@ -331,11 +331,14 @@ typedef struct {
7587         __u32 win_ctime[2];
7588         __u32 win_atime[2];
7589         __u32 win_mtime[2];
7590 -       __u32 roomToGrow[4];
7591  #else
7592 -       __u32 roomToGrow[10];
7593 +       __u32 roomToGrow[6];
7594 +
7595  #endif
7596 +       __u32 inbandShadowsObject;
7597 +       __u32 inbandIsShrink;
7598  
7599 +       __u32 reservedSpace[2];
7600         int shadowsObject;      /* This object header shadows the specified object if > 0 */
7601  
7602         /* isShrink applies to object headers written when we shrink the file (ie resize) */
7603 @@ -381,7 +384,7 @@ typedef struct {
7604  } yaffs_FileStructure;
7605  
7606  typedef struct {
7607 -       struct list_head children;      /* list of child links */
7608 +        struct ylist_head children;     /* list of child links */
7609  } yaffs_DirectoryStructure;
7610  
7611  typedef struct {
7612 @@ -408,7 +411,7 @@ struct yaffs_ObjectStruct {
7613         __u8 renameAllowed:1;   /* Some objects are not allowed to be renamed. */
7614         __u8 unlinkAllowed:1;
7615         __u8 dirty:1;           /* the object needs to be written to flash */
7616 -       __u8 valid:1;           /* When the file system is being loaded up, this
7617 +       __u8 valid:1;           /* When the file system is being loaded up, this 
7618                                  * object might be created before the data
7619                                  * is available (ie. file data records appear before the header).
7620                                  */
7621 @@ -417,33 +420,36 @@ struct yaffs_ObjectStruct {
7622         __u8 deferedFree:1;     /* For Linux kernel. Object is removed from NAND, but is
7623                                  * still in the inode cache. Free of object is defered.
7624                                  * until the inode is released.
7625 -                                */
7626 +                                 */
7627 +        __u8 beingCreated:1;   /* This object is still being created so skip some checks. */
7628  
7629 -       __u8 serial;            /* serial number of chunk in NAND. Cached here */
7630 -       __u16 sum;              /* sum of the name to speed searching */
7631 +        __u8 serial;            /* serial number of chunk in NAND. Cached here */
7632 +/*        __u16 sum_prev; */
7633 +        __u16 sum;              /* sum of the name to speed searching */
7634 +/*        __u16 sum_trailer; */
7635  
7636 -       struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
7637 +        struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
7638  
7639 -       struct list_head hashLink;      /* list of objects in this hash bucket */
7640 +        struct ylist_head hashLink;     /* list of objects in this hash bucket */
7641  
7642 -       struct list_head hardLinks;     /* all the equivalent hard linked objects */
7643 +        struct ylist_head hardLinks;    /* all the equivalent hard linked objects */
7644  
7645 -       /* directory structure stuff */
7646 -       /* also used for linking up the free list */
7647 -       struct yaffs_ObjectStruct *parent;
7648 -       struct list_head siblings;
7649 +        /* directory structure stuff */
7650 +        /* also used for linking up the free list */
7651 +        struct yaffs_ObjectStruct *parent; 
7652 +        struct ylist_head siblings;
7653  
7654         /* Where's my object header in NAND? */
7655 -       int chunkId;
7656 +       int hdrChunk;
7657  
7658         int nDataChunks;        /* Number of data chunks attached to the file. */
7659  
7660         __u32 objectId;         /* the object id value */
7661  
7662 -       __u32 yst_mode;
7663 +        __u32 yst_mode;
7664  
7665  #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
7666 -       YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
7667 +        YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
7668  #endif
7669  
7670  #ifndef __KERNEL__
7671 @@ -485,31 +491,30 @@ struct yaffs_ObjectList_struct {
7672  typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
7673  
7674  typedef struct {
7675 -       struct list_head list;
7676 -       int count;
7677 +        struct ylist_head list;
7678 +        int count;
7679  } yaffs_ObjectBucket;
7680  
7681  
7682 -/* yaffs_CheckpointObject holds the definition of an object as dumped
7683 +/* yaffs_CheckpointObject holds the definition of an object as dumped 
7684   * by checkpointing.
7685   */
7686  
7687  typedef struct {
7688          int structType;
7689 -       __u32 objectId;
7690 +       __u32 objectId;         
7691         __u32 parentId;
7692 -       int chunkId;
7693 -
7694 +       int hdrChunk;
7695         yaffs_ObjectType variantType:3;
7696 -       __u8 deleted:1;
7697 -       __u8 softDeleted:1;
7698 -       __u8 unlinked:1;
7699 -       __u8 fake:1;
7700 +       __u8 deleted:1;         
7701 +       __u8 softDeleted:1;     
7702 +       __u8 unlinked:1;        
7703 +       __u8 fake:1;            
7704         __u8 renameAllowed:1;
7705         __u8 unlinkAllowed:1;
7706 -       __u8 serial;
7707 -
7708 -       int nDataChunks;
7709 +       __u8 serial;            
7710 +       
7711 +       int nDataChunks;        
7712         __u32 fileSizeOrEquivalentObjectId;
7713  
7714  }yaffs_CheckpointObject;
7715 @@ -528,25 +533,25 @@ typedef struct {
7716  /*----------------- Device ---------------------------------*/
7717  
7718  struct yaffs_DeviceStruct {
7719 -       struct list_head devList;
7720 -       const char *name;
7721 +        struct ylist_head devList;
7722 +        const char *name;
7723  
7724 -       /* Entry parameters set up way early. Yaffs sets up the rest.*/
7725 -       int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
7726 -       int nChunksPerBlock;    /* does not need to be a power of 2 */
7727 -       int nBytesPerSpare;     /* spare area size */
7728 -       int startBlock;         /* Start block we're allowed to use */
7729 -       int endBlock;           /* End block we're allowed to use */
7730 -       int nReservedBlocks;    /* We want this tuneable so that we can reduce */
7731 +        /* Entry parameters set up way early. Yaffs sets up the rest.*/
7732 +        int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
7733 +        int nChunksPerBlock;    /* does not need to be a power of 2 */
7734 +        int spareBytesPerChunk;/* spare area size */
7735 +        int startBlock;         /* Start block we're allowed to use */
7736 +        int endBlock;           /* End block we're allowed to use */
7737 +        int nReservedBlocks;    /* We want this tuneable so that we can reduce */
7738                                 /* reserved blocks on NOR and RAM. */
7739 -
7740 -
7741 +       
7742 +       
7743         /* Stuff used by the shared space checkpointing mechanism */
7744         /* If this value is zero, then this mechanism is disabled */
7745 +       
7746 +//     int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
7747  
7748 -       int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
7749 -
7750 -
7751 +       
7752  
7753  
7754         int nShortOpCaches;     /* If <= 0, then short op caching is disabled, else
7755 @@ -561,7 +566,7 @@ struct yaffs_DeviceStruct {
7756                                  * On an mtd this holds the mtd pointer.
7757                                  */
7758          void *superBlock;
7759 -
7760 +        
7761         /* NAND access functions (Must be set before calling YAFFS)*/
7762  
7763         int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
7764 @@ -570,12 +575,13 @@ struct yaffs_DeviceStruct {
7765         int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
7766                                   int chunkInNAND, __u8 * data,
7767                                   yaffs_Spare * spare);
7768 -       int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
7769 -                                int blockInNAND);
7770 -       int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
7771 +        int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
7772 +                                 int blockInNAND);
7773 +        int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
7774 +        int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev);
7775  
7776  #ifdef CONFIG_YAFFS_YAFFS2
7777 -       int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
7778 +        int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
7779                                          int chunkInNAND, const __u8 * data,
7780                                          const yaffs_ExtendedTags * tags);
7781         int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
7782 @@ -583,25 +589,27 @@ struct yaffs_DeviceStruct {
7783                                           yaffs_ExtendedTags * tags);
7784         int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
7785         int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
7786 -                              yaffs_BlockState * state, int *sequenceNumber);
7787 +                              yaffs_BlockState * state, __u32 *sequenceNumber);
7788  #endif
7789  
7790         int isYaffs2;
7791 -
7792 -       /* The removeObjectCallback function must be supplied by OS flavours that
7793 +       
7794 +       /* The removeObjectCallback function must be supplied by OS flavours that 
7795          * need it. The Linux kernel does not use this, but yaffs direct does use
7796          * it to implement the faster readdir
7797          */
7798         void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
7799 -
7800 +       
7801         /* Callback to mark the superblock dirsty */
7802         void (*markSuperBlockDirty)(void * superblock);
7803 -
7804 +       
7805         int wideTnodesDisabled; /* Set to disable wide tnodes */
7806 -
7807 +       
7808 +       YCHAR *pathDividers;    /* String of legal path dividers */
7809 +       
7810  
7811         /* End of stuff that must be set before initialisation. */
7812 -
7813 +       
7814         /* Checkpoint control. Can be set before or after initialisation */
7815         __u8 skipCheckpointRead;
7816         __u8 skipCheckpointWrite;
7817 @@ -610,34 +618,32 @@ struct yaffs_DeviceStruct {
7818  
7819         __u16 chunkGroupBits;   /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
7820         __u16 chunkGroupSize;   /* == 2^^chunkGroupBits */
7821 -
7822 +       
7823         /* Stuff to support wide tnodes */
7824         __u32 tnodeWidth;
7825         __u32 tnodeMask;
7826 -
7827 -       /* Stuff to support various file offses to chunk/offset translations */
7828 -       /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
7829 -       __u32 crumbMask;
7830 -       __u32 crumbShift;
7831 -       __u32 crumbsPerChunk;
7832 -
7833 -       /* Straight shifting for nDataBytesPerChunk being a power of 2 */
7834 -       __u32 chunkShift;
7835 -       __u32 chunkMask;
7836 -
7837 +       
7838 +       /* Stuff for figuring out file offset to chunk conversions */
7839 +       __u32 chunkShift; /* Shift value */
7840 +       __u32 chunkDiv;   /* Divisor after shifting: 1 for power-of-2 sizes */
7841 +       __u32 chunkMask;  /* Mask to use for power-of-2 case */
7842 +
7843 +       /* Stuff to handle inband tags */
7844 +       int inbandTags;
7845 +       __u32 totalBytesPerChunk;
7846  
7847  #ifdef __KERNEL__
7848  
7849         struct semaphore sem;   /* Semaphore for waiting on erasure.*/
7850         struct semaphore grossLock;     /* Gross locking semaphore */
7851 -       __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer
7852 +       __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer 
7853                                  * at compile time so we have to allocate it.
7854                                  */
7855         void (*putSuperFunc) (struct super_block * sb);
7856  #endif
7857  
7858         int isMounted;
7859 -
7860 +       
7861         int isCheckpointed;
7862  
7863  
7864 @@ -646,7 +652,7 @@ struct yaffs_DeviceStruct {
7865         int internalEndBlock;
7866         int blockOffset;
7867         int chunkOffset;
7868 -
7869 +       
7870  
7871         /* Runtime checkpointing stuff */
7872         int checkpointPageSequence;   /* running sequence number of checkpoint pages */
7873 @@ -662,13 +668,15 @@ struct yaffs_DeviceStruct {
7874         int checkpointMaxBlocks;
7875         __u32 checkpointSum;
7876         __u32 checkpointXor;
7877 -
7878 +       
7879 +       int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */
7880 +       
7881         /* Block Info */
7882         yaffs_BlockInfo *blockInfo;
7883         __u8 *chunkBits;        /* bitmap of chunks in use */
7884         unsigned blockInfoAlt:1;        /* was allocated using alternative strategy */
7885         unsigned chunkBitsAlt:1;        /* was allocated using alternative strategy */
7886 -       int chunkBitmapStride;  /* Number of bytes of chunkBits per block.
7887 +       int chunkBitmapStride;  /* Number of bytes of chunkBits per block. 
7888                                  * Must be consistent with nChunksPerBlock.
7889                                  */
7890  
7891 @@ -684,10 +692,14 @@ struct yaffs_DeviceStruct {
7892         yaffs_TnodeList *allocatedTnodeList;
7893  
7894         int isDoingGC;
7895 +       int gcBlock;
7896 +       int gcChunk;
7897  
7898         int nObjectsCreated;
7899         yaffs_Object *freeObjects;
7900         int nFreeObjects;
7901 +       
7902 +       int nHardLinks;
7903  
7904         yaffs_ObjectList *allocatedObjectList;
7905  
7906 @@ -716,7 +728,7 @@ struct yaffs_DeviceStruct {
7907         int tagsEccUnfixed;
7908         int nDeletions;
7909         int nUnmarkedDeletions;
7910 -
7911 +       
7912         int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
7913  
7914         /* Special directories */
7915 @@ -727,7 +739,7 @@ struct yaffs_DeviceStruct {
7916          *      __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
7917          *      yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
7918          */
7919 -
7920 +       
7921         int bufferedBlock;      /* Which block is buffered here? */
7922         int doingBufferedBlockRewrite;
7923  
7924 @@ -744,9 +756,11 @@ struct yaffs_DeviceStruct {
7925         int nUnlinkedFiles;             /* Count of unlinked files. */
7926         int nBackgroundDeletions;       /* Count of background deletions. */
7927  
7928 -
7929 +       
7930 +       /* Temporary buffer management */
7931         yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
7932         int maxTemp;
7933 +       int tempInUse;
7934         int unmanagedTempAllocations;
7935         int unmanagedTempDeallocations;
7936  
7937 @@ -758,17 +772,17 @@ struct yaffs_DeviceStruct {
7938  
7939  typedef struct yaffs_DeviceStruct yaffs_Device;
7940  
7941 -/* The static layout of bllock usage etc is stored in the super block header */
7942 +/* The static layout of block usage etc is stored in the super block header */
7943  typedef struct {
7944          int StructType;
7945 -       int version;
7946 +        int version;
7947         int checkpointStartBlock;
7948         int checkpointEndBlock;
7949         int startBlock;
7950         int endBlock;
7951         int rfu[100];
7952  } yaffs_SuperBlockHeader;
7953 -
7954 +       
7955  /* The CheckpointDevice structure holds the device information that changes at runtime and
7956   * must be preserved over unmount/mount cycles.
7957   */
7958 @@ -797,18 +811,6 @@ typedef struct {
7959      __u32 head;
7960  } yaffs_CheckpointValidity;
7961  
7962 -/* Function to manipulate block info */
7963 -static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
7964 -{
7965 -       if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
7966 -               T(YAFFS_TRACE_ERROR,
7967 -                 (TSTR
7968 -                  ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
7969 -                  blk));
7970 -               YBUG();
7971 -       }
7972 -       return &dev->blockInfo[blk - dev->internalStartBlock];
7973 -}
7974  
7975  /*----------------------- YAFFS Functions -----------------------*/
7976  
7977 @@ -834,13 +836,13 @@ int yaffs_GetAttributes(yaffs_Object * o
7978  
7979  /* File operations */
7980  int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
7981 -                          int nBytes);
7982 +                           int nBytes);
7983  int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
7984 -                         int nBytes, int writeThrough);
7985 +                          int nBytes, int writeThrough);
7986  int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
7987  
7988  yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
7989 -                             __u32 mode, __u32 uid, __u32 gid);
7990 +                              __u32 mode, __u32 uid, __u32 gid);
7991  int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
7992  
7993  /* Flushing and checkpointing */
7994 @@ -899,4 +901,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
7995  int yaffs_CheckFF(__u8 * buffer, int nBytes);
7996  void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
7997  
7998 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
7999 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo);
8000 +
8001  #endif
8002 --- a/fs/yaffs2/moduleconfig.h
8003 +++ b/fs/yaffs2/moduleconfig.h
8004 @@ -54,11 +54,11 @@ that you need to continue to support.  N
8005  older-style format.
8006  Note: Use of this option generally requires that MTD's oob layout be
8007  adjusted to use the older-style format.  See notes on tags formats and
8008 -MTD versions.
8009 +MTD versions in yaffs_mtdif1.c.
8010  */
8011  /* Default: Not selected */
8012  /* Meaning: Use older-style on-NAND data format with pageStatus byte */
8013 -#define CONFIG_YAFFS_9BYTE_TAGS
8014 +//#define CONFIG_YAFFS_9BYTE_TAGS
8015  
8016  #endif /* YAFFS_OUT_OF_TREE */
8017  
8018 --- a/fs/yaffs2/yaffs_mtdif1.h
8019 +++ b/fs/yaffs2/yaffs_mtdif1.h
8020 @@ -23,6 +23,6 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
8021  int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
8022  
8023  int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
8024 -       yaffs_BlockState * state, int *sequenceNumber);
8025 +       yaffs_BlockState * state, __u32 *sequenceNumber);
8026  
8027  #endif
8028 --- a/fs/yaffs2/yaffs_mtdif2.h
8029 +++ b/fs/yaffs2/yaffs_mtdif2.h
8030 @@ -24,6 +24,6 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
8031                                        __u8 * data, yaffs_ExtendedTags * tags);
8032  int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
8033  int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
8034 -                           yaffs_BlockState * state, int *sequenceNumber);
8035 +                           yaffs_BlockState * state, __u32 *sequenceNumber);
8036  
8037  #endif
8038 --- a/fs/yaffs2/yaffs_checkptrw.c
8039 +++ b/fs/yaffs2/yaffs_checkptrw.c
8040 @@ -12,11 +12,11 @@
8041   */
8042  
8043  const char *yaffs_checkptrw_c_version =
8044 -    "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $";
8045 +    "$Id: yaffs_checkptrw.c,v 1.17 2008-08-12 22:51:57 charles Exp $";
8046  
8047  
8048  #include "yaffs_checkptrw.h"
8049 -
8050 +#include "yaffs_getblockinfo.h"
8051  
8052  static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
8053  {
8054 @@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
8055                 return 0;
8056  
8057         if(!dev->checkpointBuffer)
8058 -               dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
8059 +               dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
8060         if(!dev->checkpointBuffer)
8061                 return 0;
8062  
8063 @@ -324,6 +324,7 @@ int yaffs_CheckpointRead(yaffs_Device *d
8064                                                               &tags);
8065  
8066                                 if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
8067 +                                  tags.eccResult > YAFFS_ECC_RESULT_FIXED ||
8068                                    tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
8069                                    ok = 0;
8070  
8071 --- a/fs/yaffs2/yaffs_tagscompat.c
8072 +++ b/fs/yaffs2/yaffs_tagscompat.c
8073 @@ -14,6 +14,7 @@
8074  #include "yaffs_guts.h"
8075  #include "yaffs_tagscompat.h"
8076  #include "yaffs_ecc.h"
8077 +#include "yaffs_getblockinfo.h"
8078  
8079  static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
8080  #ifdef NOTYET
8081 @@ -252,6 +253,9 @@ static int yaffs_ReadChunkFromNAND(struc
8082                 /* Must allocate enough memory for spare+2*sizeof(int) */
8083                 /* for ecc results from device. */
8084                 struct yaffs_NANDSpare nspare;
8085 +               
8086 +               memset(&nspare,0,sizeof(nspare));
8087 +               
8088                 retVal =
8089                     dev->readChunkFromNAND(dev, chunkInNAND, data,
8090                                            (yaffs_Spare *) & nspare);
8091 @@ -336,7 +340,7 @@ static void yaffs_HandleReadDataError(ya
8092         int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
8093  
8094         /* Mark the block for retirement */
8095 -       yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
8096 +       yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
8097         T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
8098           (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
8099  
8100 @@ -414,7 +418,16 @@ int yaffs_TagsCompatabilityWriteChunkWit
8101         } else {
8102                 tags.objectId = eTags->objectId;
8103                 tags.chunkId = eTags->chunkId;
8104 -               tags.byteCount = eTags->byteCount;
8105 +
8106 +               tags.byteCountLSB = eTags->byteCount & 0x3ff;
8107 +               
8108 +               if(dev->nDataBytesPerChunk >= 1024){
8109 +                       tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
8110 +               } else {
8111 +                       tags.byteCountMSB = 3;
8112 +               }
8113 +               
8114 +
8115                 tags.serialNumber = eTags->serialNumber;
8116  
8117                 if (!dev->useNANDECC && data) {
8118 @@ -435,10 +448,10 @@ int yaffs_TagsCompatabilityReadChunkWith
8119  
8120         yaffs_Spare spare;
8121         yaffs_Tags tags;
8122 -       yaffs_ECCResult eccResult;
8123 +       yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;
8124  
8125         static yaffs_Spare spareFF;
8126 -       static int init;
8127 +       static int init = 0;
8128  
8129         if (!init) {
8130                 memset(&spareFF, 0xFF, sizeof(spareFF));
8131 @@ -466,7 +479,11 @@ int yaffs_TagsCompatabilityReadChunkWith
8132  
8133                                 eTags->objectId = tags.objectId;
8134                                 eTags->chunkId = tags.chunkId;
8135 -                               eTags->byteCount = tags.byteCount;
8136 +                               eTags->byteCount = tags.byteCountLSB;
8137 +
8138 +                               if(dev->nDataBytesPerChunk >= 1024)
8139 +                                       eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
8140 +
8141                                 eTags->serialNumber = tags.serialNumber;
8142                         }
8143                 }
8144 @@ -497,9 +514,9 @@ int yaffs_TagsCompatabilityMarkNANDBlock
8145  }
8146  
8147  int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
8148 -                                         int blockNo, yaffs_BlockState *
8149 -                                         state,
8150 -                                         int *sequenceNumber)
8151 +                                         int blockNo,
8152 +                                         yaffs_BlockState *state,
8153 +                                         __u32 *sequenceNumber)
8154  {
8155  
8156         yaffs_Spare spare0, spare1;
8157 --- a/fs/yaffs2/yaffs_mtdif.c
8158 +++ b/fs/yaffs2/yaffs_mtdif.c
8159 @@ -12,7 +12,7 @@
8160   */
8161  
8162  const char *yaffs_mtdif_c_version =
8163 -    "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $";
8164 +    "$Id: yaffs_mtdif.c,v 1.21 2007-12-13 15:35:18 wookey Exp $";
8165  
8166  #include "yportenv.h"
8167  
8168 @@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version =
8169  #include "linux/time.h"
8170  #include "linux/mtd/nand.h"
8171  
8172 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
8173 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
8174  static struct nand_oobinfo yaffs_oobinfo = {
8175         .useecc = 1,
8176         .eccbytes = 6,
8177 @@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccin
8178  };
8179  #endif
8180  
8181 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
8182 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
8183  static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
8184  {
8185         oob[0] = spare->tagByte0;
8186 @@ -75,14 +75,14 @@ int nandmtd_WriteChunkToNAND(yaffs_Devic
8187                              const __u8 * data, const yaffs_Spare * spare)
8188  {
8189         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
8190 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
8191 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
8192         struct mtd_oob_ops ops;
8193  #endif
8194         size_t dummy;
8195         int retval = 0;
8196  
8197         loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
8198 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
8199 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
8200         __u8 spareAsBytes[8]; /* OOB */
8201  
8202         if (data && !spare)
8203 @@ -139,14 +139,14 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi
8204                               yaffs_Spare * spare)
8205  {
8206         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
8207 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
8208 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
8209         struct mtd_oob_ops ops;
8210  #endif
8211         size_t dummy;
8212         int retval = 0;
8213  
8214         loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
8215 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
8216 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
8217         __u8 spareAsBytes[8]; /* OOB */
8218  
8219         if (data && !spare)
8220 --- a/fs/yaffs2/yaffs_nandemul2k.h
8221 +++ b/fs/yaffs2/yaffs_nandemul2k.h
8222 @@ -22,13 +22,13 @@
8223  
8224  int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
8225                                         int chunkInNAND, const __u8 * data,
8226 -                                       yaffs_ExtendedTags * tags);
8227 +                                       const yaffs_ExtendedTags * tags);
8228  int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
8229                                          int chunkInNAND, __u8 * data,
8230                                          yaffs_ExtendedTags * tags);
8231  int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
8232  int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
8233 -                             yaffs_BlockState * state, int *sequenceNumber);
8234 +                             yaffs_BlockState * state, __u32 *sequenceNumber);
8235  int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
8236                                 int blockInNAND);
8237  int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);