[kernel] generic/2.6.28: fix yaffs cvs patch
[10.03/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_fs.c
752 +++ b/fs/yaffs2/yaffs_fs.c
753 @@ -32,7 +32,7 @@
754   */
755  
756  const char *yaffs_fs_c_version =
757 -    "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $";
758 +    "$Id: yaffs_fs.c,v 1.71 2009-01-22 00:45:54 charles Exp $";
759  extern const char *yaffs_guts_c_version;
760  
761  #include <linux/version.h>
762 @@ -43,7 +43,6 @@ extern const char *yaffs_guts_c_version;
763  #include <linux/module.h>
764  #include <linux/slab.h>
765  #include <linux/init.h>
766 -#include <linux/list.h>
767  #include <linux/fs.h>
768  #include <linux/proc_fs.h>
769  #include <linux/smp_lock.h>
770 @@ -53,6 +52,8 @@ extern const char *yaffs_guts_c_version;
771  #include <linux/string.h>
772  #include <linux/ctype.h>
773  
774 +#include "asm/div64.h"
775 +
776  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
777  
778  #include <linux/statfs.h>      /* Added NCB 15-8-2003 */
779 @@ -76,6 +77,12 @@ extern const char *yaffs_guts_c_version;
780  
781  #endif
782  
783 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
784 +#define YPROC_ROOT  &proc_root
785 +#else
786 +#define YPROC_ROOT  NULL
787 +#endif
788 +
789  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
790  #define WRITE_SIZE_STR "writesize"
791  #define WRITE_SIZE(mtd) (mtd)->writesize
792 @@ -84,6 +91,13 @@ extern const char *yaffs_guts_c_version;
793  #define WRITE_SIZE(mtd) (mtd)->oobblock
794  #endif
795  
796 +#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
797 +#define YAFFS_USE_WRITE_BEGIN_END 1
798 +#else
799 +#define YAFFS_USE_WRITE_BEGIN_END 0
800 +#endif
801 +
802 +
803  #include <asm/uaccess.h>
804  
805  #include "yportenv.h"
806 @@ -96,14 +110,30 @@ extern const char *yaffs_guts_c_version;
807  
808  unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;
809  unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
810 +unsigned int yaffs_auto_checkpoint = 1;
811  
812  /* Module Parameters */
813  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
814  module_param(yaffs_traceMask,uint,0644);
815  module_param(yaffs_wr_attempts,uint,0644);
816 +module_param(yaffs_auto_checkpoint,uint,0644);
817  #else
818  MODULE_PARM(yaffs_traceMask,"i");
819  MODULE_PARM(yaffs_wr_attempts,"i");
820 +MODULE_PARM(yaffs_auto_checkpoint,"i");
821 +#endif
822 +
823 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
824 +/* use iget and read_inode */
825 +#define Y_IGET(sb,inum) iget((sb),(inum))
826 +static void yaffs_read_inode(struct inode *inode);
827 +
828 +#else
829 +/* Call local equivalent */
830 +#define YAFFS_USE_OWN_IGET
831 +#define Y_IGET(sb,inum) yaffs_iget((sb),(inum))
832 +
833 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino);
834  #endif
835  
836  /*#define T(x) printk x */
837 @@ -127,6 +157,8 @@ static void yaffs_put_super(struct super
838  
839  static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
840                                 loff_t * pos);
841 +static ssize_t yaffs_hold_space(struct file *f);
842 +static void yaffs_release_space(struct file *f);
843  
844  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
845  static int yaffs_file_flush(struct file *file, fl_owner_t id);
846 @@ -181,9 +213,11 @@ static int yaffs_statfs(struct super_blo
847  #else
848  static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
849  #endif
850 -static void yaffs_read_inode(struct inode *inode);
851  
852 +#ifdef YAFFS_HAS_PUT_INODE
853  static void yaffs_put_inode(struct inode *inode);
854 +#endif
855 +
856  static void yaffs_delete_inode(struct inode *);
857  static void yaffs_clear_inode(struct inode *);
858  
859 @@ -193,10 +227,22 @@ static int yaffs_writepage(struct page *
860  #else
861  static int yaffs_writepage(struct page *page);
862  #endif
863 +
864 +
865 +#if (YAFFS_USE_WRITE_BEGIN_END != 0)
866 +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
867 +                             loff_t pos, unsigned len, unsigned flags,
868 +                          struct page **pagep, void **fsdata);
869 +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
870 +                          loff_t pos, unsigned len, unsigned copied,
871 +                          struct page *pg, void *fsdadata);
872 +#else
873  static int yaffs_prepare_write(struct file *f, struct page *pg,
874                                unsigned offset, unsigned to);
875  static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
876                               unsigned to);
877 +                                                                                                
878 +#endif
879  
880  static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
881                           int buflen);
882 @@ -209,8 +255,13 @@ static int yaffs_follow_link(struct dent
883  static struct address_space_operations yaffs_file_address_operations = {
884         .readpage = yaffs_readpage,
885         .writepage = yaffs_writepage,
886 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
887 +       .write_begin = yaffs_write_begin,
888 +       .write_end = yaffs_write_end,
889 +#else
890         .prepare_write = yaffs_prepare_write,
891         .commit_write = yaffs_commit_write,
892 +#endif
893  };
894  
895  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
896 @@ -224,6 +275,7 @@ static struct file_operations yaffs_file
897         .fsync = yaffs_sync_object,
898         .splice_read = generic_file_splice_read,
899         .splice_write = generic_file_splice_write,
900 +       .llseek = generic_file_llseek,
901  };
902  
903  #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
904 @@ -284,8 +336,13 @@ static struct file_operations yaffs_dir_
905  
906  static struct super_operations yaffs_super_ops = {
907         .statfs = yaffs_statfs,
908 +
909 +#ifndef YAFFS_USE_OWN_IGET
910         .read_inode = yaffs_read_inode,
911 +#endif
912 +#ifdef YAFFS_HAS_PUT_INODE
913         .put_inode = yaffs_put_inode,
914 +#endif
915         .put_super = yaffs_put_super,
916         .delete_inode = yaffs_delete_inode,
917         .clear_inode = yaffs_clear_inode,
918 @@ -429,6 +486,9 @@ static struct dentry *yaffs_lookup(struc
919  
920  }
921  
922 +
923 +#ifdef YAFFS_HAS_PUT_INODE
924 +
925  /* For now put inode is just for debugging
926   * Put inode is called when the inode **structure** is put.
927   */
928 @@ -439,6 +499,7 @@ static void yaffs_put_inode(struct inode
929            atomic_read(&inode->i_count)));
930  
931  }
932 +#endif
933  
934  /* clear is called to tell the fs to release any per-inode data it holds */
935  static void yaffs_clear_inode(struct inode *inode)
936 @@ -667,6 +728,64 @@ static int yaffs_writepage(struct page *
937         return (nWritten == nBytes) ? 0 : -ENOSPC;
938  }
939  
940 +
941 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
942 +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
943 +                             loff_t pos, unsigned len, unsigned flags,
944 +                          struct page **pagep, void **fsdata)
945 +
946 +{
947 +       struct page *pg = NULL;
948 +        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
949 +        uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
950 +        uint32_t to = offset + len;
951 +        
952 +        int ret = 0;
953 +        int space_held = 0;
954 +        
955 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "start yaffs_write_begin\n"));
956 +       /* Get a page */
957 +       pg = __grab_cache_page(mapping,index);
958 +       *pagep = pg;    
959 +       if(!pg){
960 +               ret =  -ENOMEM;
961 +               goto out;
962 +       }
963 +       /* Get fs space */
964 +       space_held = yaffs_hold_space(filp);
965 +       
966 +       if(!space_held){
967 +               ret = -ENOSPC;
968 +               goto out;
969 +       }
970 +               
971 +       /* Update page if required */
972 +       
973 +       if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
974 +               ret = yaffs_readpage_nolock(filp, pg);
975 +       
976 +       if(ret)
977 +               goto out;
978 +
979 +       /* Happy path return */
980 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin - ok\n"));
981 +               
982 +       return 0;
983 +               
984 +out:
985 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin fail returning %d\n",ret));
986 +       if(space_held){
987 +               yaffs_release_space(filp);
988 +       }
989 +       if(pg) {
990 +               unlock_page(pg);
991 +               page_cache_release(pg);
992 +       }
993 +       return ret;
994 +}
995 +
996 +#else
997 +
998  static int yaffs_prepare_write(struct file *f, struct page *pg,
999                                unsigned offset, unsigned to)
1000  {
1001 @@ -674,22 +793,69 @@ static int yaffs_prepare_write(struct fi
1002         T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));
1003         if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
1004                 return yaffs_readpage_nolock(f, pg);
1005 -
1006         return 0;
1007  
1008  }
1009 +#endif
1010 +
1011 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
1012 +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
1013 +                          loff_t pos, unsigned len, unsigned copied,
1014 +                          struct page *pg, void *fsdadata)
1015 +{
1016 +       int ret = 0;
1017 +       void *addr, *kva;
1018 +        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1019 +        uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE -1); 
1020 +
1021 +
1022 +       
1023 +       kva=kmap(pg);
1024 +       addr = kva + offset_into_page;
1025 +
1026 +       T(YAFFS_TRACE_OS,
1027 +         (KERN_DEBUG "yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned) addr,
1028 +          (int)pos, copied));
1029 +
1030 +       ret = yaffs_file_write(filp, addr, copied, &pos);
1031 +
1032 +       if (ret != copied) {
1033 +               T(YAFFS_TRACE_OS,
1034 +                 (KERN_DEBUG
1035 +                  "yaffs_write_end not same size ret %d  copied %d\n",
1036 +                  ret, copied ));
1037 +               SetPageError(pg);
1038 +               ClearPageUptodate(pg);
1039 +       } else {
1040 +               SetPageUptodate(pg);
1041 +       }
1042 +
1043 +       kunmap(pg);
1044 +
1045 +       yaffs_release_space(filp);
1046 +       unlock_page(pg);
1047 +       page_cache_release(pg);
1048 +       return ret;
1049 +}
1050 +#else
1051  
1052  static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
1053                               unsigned to)
1054  {
1055  
1056 -       void *addr = page_address(pg) + offset;
1057 +       void *addr, *kva;
1058 +       
1059         loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
1060         int nBytes = to - offset;
1061         int nWritten;
1062  
1063         unsigned spos = pos;
1064 -       unsigned saddr = (unsigned)addr;
1065 +       unsigned saddr;
1066 +       
1067 +       kva=kmap(pg);
1068 +       addr = kva + offset;
1069 +
1070 +       saddr = (unsigned) addr;
1071  
1072         T(YAFFS_TRACE_OS,
1073           (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr,
1074 @@ -708,6 +874,8 @@ static int yaffs_commit_write(struct fil
1075                 SetPageUptodate(pg);
1076         }
1077  
1078 +       kunmap(pg);
1079 +
1080         T(YAFFS_TRACE_OS,
1081           (KERN_DEBUG "yaffs_commit_write returning %d\n",
1082            nWritten == nBytes ? 0 : nWritten));
1083 @@ -715,6 +883,8 @@ static int yaffs_commit_write(struct fil
1084         return nWritten == nBytes ? 0 : nWritten;
1085  
1086  }
1087 +#endif
1088 +
1089  
1090  static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
1091  {
1092 @@ -753,6 +923,8 @@ static void yaffs_FillInodeFromObject(st
1093                         break;
1094                 }
1095  
1096 +               inode->i_flags |= S_NOATIME;
1097 +               
1098                 inode->i_ino = obj->objectId;
1099                 inode->i_mode = obj->yst_mode;
1100                 inode->i_uid = obj->yst_uid;
1101 @@ -844,7 +1016,9 @@ struct inode *yaffs_get_inode(struct sup
1102         T(YAFFS_TRACE_OS,
1103           (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
1104  
1105 -       inode = iget(sb, obj->objectId);
1106 +       inode = Y_IGET(sb, obj->objectId);
1107 +       if(IS_ERR(inode))
1108 +         return NULL;
1109  
1110         /* NB Side effect: iget calls back to yaffs_read_inode(). */
1111         /* iget also increments the inode's i_count */
1112 @@ -910,13 +1084,55 @@ static ssize_t yaffs_file_write(struct f
1113         return nWritten == 0 ? -ENOSPC : nWritten;
1114  }
1115  
1116 +/* Space holding and freeing is done to ensure we have space available for write_begin/end */
1117 +/* For now we just assume few parallel writes and check against a small number. */
1118 +/* Todo: need to do this with a counter to handle parallel reads better */
1119 +
1120 +static ssize_t yaffs_hold_space(struct file *f)
1121 +{
1122 +       yaffs_Object *obj;
1123 +       yaffs_Device *dev;
1124 +       
1125 +       int nFreeChunks;
1126 +
1127 +       
1128 +       obj = yaffs_DentryToObject(f->f_dentry);
1129 +
1130 +       dev = obj->myDev;
1131 +
1132 +       yaffs_GrossLock(dev);
1133 +
1134 +       nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
1135 +       
1136 +       yaffs_GrossUnlock(dev);
1137 +
1138 +       return (nFreeChunks > 20) ? 1 : 0;
1139 +}
1140 +
1141 +static void yaffs_release_space(struct file *f)
1142 +{
1143 +       yaffs_Object *obj;
1144 +       yaffs_Device *dev;
1145 +       
1146 +       
1147 +       obj = yaffs_DentryToObject(f->f_dentry);
1148 +
1149 +       dev = obj->myDev;
1150 +
1151 +       yaffs_GrossLock(dev);
1152 +
1153 +       
1154 +       yaffs_GrossUnlock(dev);
1155 +
1156 +}
1157 +
1158  static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
1159  {
1160         yaffs_Object *obj;
1161         yaffs_Device *dev;
1162         struct inode *inode = f->f_dentry->d_inode;
1163         unsigned long offset, curoffs;
1164 -       struct list_head *i;
1165 +       struct ylist_head *i;
1166         yaffs_Object *l;
1167  
1168         char name[YAFFS_MAX_NAME_LENGTH + 1];
1169 @@ -965,10 +1181,10 @@ static int yaffs_readdir(struct file *f,
1170                 f->f_version = inode->i_version;
1171         }
1172  
1173 -       list_for_each(i, &obj->variant.directoryVariant.children) {
1174 +       ylist_for_each(i, &obj->variant.directoryVariant.children) {
1175                 curoffs++;
1176                 if (curoffs >= offset) {
1177 -                       l = list_entry(i, yaffs_Object, siblings);
1178 +                       l = ylist_entry(i, yaffs_Object, siblings);
1179  
1180                         yaffs_GetObjectName(l, name,
1181                                             YAFFS_MAX_NAME_LENGTH + 1);
1182 @@ -1269,7 +1485,7 @@ static int yaffs_rename(struct inode *ol
1183  
1184         if (target &&
1185             target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
1186 -           !list_empty(&target->variant.directoryVariant.children)) {
1187 +           !ylist_empty(&target->variant.directoryVariant.children)) {
1188  
1189                 T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
1190  
1191 @@ -1350,25 +1566,47 @@ static int yaffs_statfs(struct super_blo
1192         buf->f_type = YAFFS_MAGIC;
1193         buf->f_bsize = sb->s_blocksize;
1194         buf->f_namelen = 255;
1195 -       if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1196 -
1197 +       
1198 +       if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
1199 +               /* Do this if chunk size is not a power of 2 */
1200 +               
1201 +               uint64_t bytesInDev;
1202 +               uint64_t bytesFree;
1203 +
1204 +               bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
1205 +                            ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
1206 +       
1207 +               do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
1208 +               buf->f_blocks = bytesInDev;
1209 +
1210 +               bytesFree  = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
1211 +                            ((uint64_t)(dev->nDataBytesPerChunk));
1212 +       
1213 +               do_div(bytesFree,sb->s_blocksize);
1214 +       
1215 +               buf->f_bfree = bytesFree;
1216 +       
1217 +       } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1218 +       
1219                 buf->f_blocks =
1220 -                   (dev->endBlock - dev->startBlock +
1221 -                    1) * dev->nChunksPerBlock / (sb->s_blocksize /
1222 -                                                 dev->nDataBytesPerChunk);
1223 -               buf->f_bfree =
1224 -                   yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
1225 -                                                       dev->nDataBytesPerChunk);
1226 +                          (dev->endBlock - dev->startBlock + 1) * 
1227 +                           dev->nChunksPerBlock / 
1228 +                           (sb->s_blocksize / dev->nDataBytesPerChunk);
1229 +               buf->f_bfree =
1230 +                          yaffs_GetNumberOfFreeChunks(dev) / 
1231 +                          (sb->s_blocksize / dev->nDataBytesPerChunk);
1232         } else {
1233 -
1234 -               buf->f_blocks =
1235 -                   (dev->endBlock - dev->startBlock +
1236 -                    1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
1237 -                                                 sb->s_blocksize);
1238 -               buf->f_bfree =
1239 -                   yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
1240 -                                                       sb->s_blocksize);
1241 +              buf->f_blocks =
1242 +                          (dev->endBlock - dev->startBlock + 1) * 
1243 +                          dev->nChunksPerBlock * 
1244 +                          (dev->nDataBytesPerChunk / sb->s_blocksize);
1245 +                          
1246 +                      buf->f_bfree =
1247 +                          yaffs_GetNumberOfFreeChunks(dev) * 
1248 +                          (dev->nDataBytesPerChunk / sb->s_blocksize);
1249         }
1250 +       
1251 +       
1252         buf->f_files = 0;
1253         buf->f_ffree = 0;
1254         buf->f_bavail = buf->f_bfree;
1255 @@ -1378,7 +1616,6 @@ static int yaffs_statfs(struct super_blo
1256  }
1257  
1258  
1259 -/**
1260  static int yaffs_do_sync_fs(struct super_block *sb)
1261  {
1262  
1263 @@ -1388,8 +1625,10 @@ static int yaffs_do_sync_fs(struct super
1264         if(sb->s_dirt) {
1265                 yaffs_GrossLock(dev);
1266  
1267 -               if(dev)
1268 +               if(dev){
1269 +                       yaffs_FlushEntireDeviceCache(dev);
1270                         yaffs_CheckpointSave(dev);
1271 +               }
1272  
1273                 yaffs_GrossUnlock(dev);
1274  
1275 @@ -1397,7 +1636,7 @@ static int yaffs_do_sync_fs(struct super
1276         }
1277         return 0;
1278  }
1279 -**/
1280 +
1281  
1282  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1283  static void yaffs_write_super(struct super_block *sb)
1284 @@ -1407,8 +1646,10 @@ static int yaffs_write_super(struct supe
1285  {
1286  
1287         T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
1288 +       if (yaffs_auto_checkpoint >= 2)
1289 +               yaffs_do_sync_fs(sb);
1290  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
1291 -       return 0; /* yaffs_do_sync_fs(sb);*/
1292 +       return 0; 
1293  #endif
1294  }
1295  
1296 @@ -1422,10 +1663,48 @@ static int yaffs_sync_fs(struct super_bl
1297  
1298         T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
1299  
1300 -       return 0; /* yaffs_do_sync_fs(sb);*/
1301 +       if (yaffs_auto_checkpoint >= 1)
1302 +               yaffs_do_sync_fs(sb);
1303 +       
1304 +       return 0; 
1305  
1306  }
1307  
1308 +#ifdef YAFFS_USE_OWN_IGET
1309 +
1310 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino)
1311 +{
1312 +       struct inode *inode;
1313 +       yaffs_Object *obj;
1314 +       yaffs_Device *dev = yaffs_SuperToDevice(sb);
1315 +
1316 +       T(YAFFS_TRACE_OS,
1317 +         (KERN_DEBUG "yaffs_iget for %lu\n", ino));
1318 +
1319 +       inode = iget_locked(sb, ino);
1320 +       if (!inode)
1321 +               return ERR_PTR(-ENOMEM);
1322 +       if (!(inode->i_state & I_NEW))
1323 +               return inode;
1324 +
1325 +       /* NB This is called as a side effect of other functions, but
1326 +       * we had to release the lock to prevent deadlocks, so
1327 +       * need to lock again.
1328 +       */
1329 +    
1330 +       yaffs_GrossLock(dev);
1331 +
1332 +       obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
1333 +
1334 +       yaffs_FillInodeFromObject(inode, obj);
1335 +
1336 +       yaffs_GrossUnlock(dev);
1337 +       
1338 +       unlock_new_inode(inode);
1339 +       return inode;
1340 +}
1341 +
1342 +#else
1343  
1344  static void yaffs_read_inode(struct inode *inode)
1345  {
1346 @@ -1449,7 +1728,9 @@ static void yaffs_read_inode(struct inod
1347         yaffs_GrossUnlock(dev);
1348  }
1349  
1350 -static LIST_HEAD(yaffs_dev_list);
1351 +#endif
1352 +
1353 +static YLIST_HEAD(yaffs_dev_list);
1354  
1355  #if 0 // not used
1356  static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
1357 @@ -1503,7 +1784,7 @@ static void yaffs_put_super(struct super
1358         yaffs_GrossUnlock(dev);
1359  
1360         /* we assume this is protected by lock_kernel() in mount/umount */
1361 -       list_del(&dev->devList);
1362 +       ylist_del(&dev->devList);
1363  
1364         if(dev->spareBuffer){
1365                 YFREE(dev->spareBuffer);
1366 @@ -1532,8 +1813,8 @@ static void yaffs_MarkSuperBlockDirty(vo
1367         struct super_block *sb = (struct super_block *)vsb;
1368  
1369         T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb));
1370 -//     if(sb)
1371 -//             sb->s_dirt = 1;
1372 +       if(sb)
1373 +               sb->s_dirt = 1;
1374  }
1375  
1376  typedef struct {
1377 @@ -1602,6 +1883,7 @@ static struct super_block *yaffs_interna
1378  
1379         sb->s_magic = YAFFS_MAGIC;
1380         sb->s_op = &yaffs_super_ops;
1381 +       sb->s_flags |= MS_NOATIME;
1382  
1383         if (!sb)
1384                 printk(KERN_INFO "yaffs: sb is NULL\n");
1385 @@ -1678,22 +1960,15 @@ static struct super_block *yaffs_interna
1386  #ifdef CONFIG_YAFFS_AUTO_YAFFS2
1387  
1388         if (yaffsVersion == 1 &&
1389 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1390 -           mtd->writesize >= 2048) {
1391 -#else
1392 -           mtd->oobblock >= 2048) {
1393 -#endif
1394 +           WRITE_SIZE(mtd) >= 2048) {
1395             T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
1396             yaffsVersion = 2;
1397         }
1398  
1399         /* Added NCB 26/5/2006 for completeness */
1400 -       if (yaffsVersion == 2 &&
1401 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1402 -           mtd->writesize == 512) {
1403 -#else
1404 -           mtd->oobblock == 512) {
1405 -#endif
1406 +       if (yaffsVersion == 2 && 
1407 +           !options.inband_tags &&
1408 +           WRITE_SIZE(mtd) == 512){
1409             T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
1410             yaffsVersion = 1;
1411         }
1412 @@ -1719,12 +1994,9 @@ static struct super_block *yaffs_interna
1413                         return NULL;
1414                 }
1415  
1416 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1417 -               if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1418 -#else
1419 -               if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1420 -#endif
1421 -                   mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
1422 +               if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1423 +                   mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
1424 +                   !options.inband_tags) {
1425                         T(YAFFS_TRACE_ALWAYS,
1426                           ("yaffs: MTD device does not have the "
1427                            "right page sizes\n"));
1428 @@ -1784,9 +2056,10 @@ static struct super_block *yaffs_interna
1429         dev->startBlock = 0;
1430         dev->endBlock = nBlocks - 1;
1431         dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
1432 -       dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
1433 +       dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
1434         dev->nReservedBlocks = 5;
1435         dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
1436 +       dev->inbandTags = options.inband_tags;
1437  
1438         /* ... and the functions. */
1439         if (yaffsVersion == 2) {
1440 @@ -1799,15 +2072,14 @@ static struct super_block *yaffs_interna
1441                 dev->spareBuffer = YMALLOC(mtd->oobsize);
1442                 dev->isYaffs2 = 1;
1443  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1444 -               dev->nDataBytesPerChunk = mtd->writesize;
1445 +               dev->totalBytesPerChunk = mtd->writesize;
1446                 dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
1447  #else
1448 -               dev->nDataBytesPerChunk = mtd->oobblock;
1449 +               dev->totalBytesPerChunk = mtd->oobblock;
1450                 dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
1451  #endif
1452                 nBlocks = mtd->size / mtd->erasesize;
1453  
1454 -               dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;
1455                 dev->startBlock = 0;
1456                 dev->endBlock = nBlocks - 1;
1457         } else {
1458 @@ -1847,7 +2119,7 @@ static struct super_block *yaffs_interna
1459         dev->skipCheckpointWrite = options.skip_checkpoint_write;
1460  
1461         /* we assume this is protected by lock_kernel() in mount/umount */
1462 -       list_add_tail(&dev->devList, &yaffs_dev_list);
1463 +       ylist_add_tail(&dev->devList, &yaffs_dev_list);
1464  
1465         init_MUTEX(&dev->grossLock);
1466  
1467 @@ -1884,6 +2156,9 @@ static struct super_block *yaffs_interna
1468                 return NULL;
1469         }
1470         sb->s_root = root;
1471 +       sb->s_dirt = !dev->isCheckpointed;
1472 +       T(YAFFS_TRACE_ALWAYS,
1473 +         ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));
1474  
1475         T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
1476         return sb;
1477 @@ -1990,12 +2265,12 @@ static char *yaffs_dump_dev(char *buf, y
1478  {
1479         buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
1480         buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
1481 +       buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);
1482         buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);
1483         buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
1484         buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
1485         buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
1486         buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks);
1487 -       buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks);
1488         buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);
1489         buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
1490         buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
1491 @@ -2006,10 +2281,8 @@ static char *yaffs_dump_dev(char *buf, y
1492         buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
1493         buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
1494         buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
1495 -       buf +=
1496 -           sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1497 -       buf +=
1498 -           sprintf(buf, "passiveGCs......... %d\n",
1499 +       buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1500 +       buf += sprintf(buf, "passiveGCs......... %d\n",
1501                     dev->passiveGarbageCollections);
1502         buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
1503         buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches);
1504 @@ -2025,6 +2298,7 @@ static char *yaffs_dump_dev(char *buf, y
1505             sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
1506         buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
1507         buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
1508 +       buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
1509  
1510         return buf;
1511  }
1512 @@ -2033,7 +2307,7 @@ static int yaffs_proc_read(char *page,
1513                            char **start,
1514                            off_t offset, int count, int *eof, void *data)
1515  {
1516 -       struct list_head *item;
1517 +       struct ylist_head *item;
1518         char *buf = page;
1519         int step = offset;
1520         int n = 0;
1521 @@ -2057,8 +2331,8 @@ static int yaffs_proc_read(char *page,
1522         lock_kernel();
1523  
1524         /* Locate and print the Nth entry.  Order N-squared but N is small. */
1525 -       list_for_each(item, &yaffs_dev_list) {
1526 -               yaffs_Device *dev = list_entry(item, yaffs_Device, devList);
1527 +       ylist_for_each(item, &yaffs_dev_list) {
1528 +               yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList);
1529                 if (n < step) {
1530                         n++;
1531                         continue;
1532 @@ -2231,7 +2505,7 @@ static int __init init_yaffs_fs(void)
1533         /* Install the proc_fs entry */
1534         my_proc_entry = create_proc_entry("yaffs",
1535                                                S_IRUGO | S_IFREG,
1536 -                                              &proc_root);
1537 +                                              YPROC_ROOT);
1538  
1539         if (my_proc_entry) {
1540                 my_proc_entry->write_proc = yaffs_proc_write;
1541 @@ -2277,7 +2551,7 @@ static void __exit exit_yaffs_fs(void)
1542         T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__
1543                                " removing. \n"));
1544  
1545 -       remove_proc_entry("yaffs", &proc_root);
1546 +       remove_proc_entry("yaffs", YPROC_ROOT);
1547  
1548         fsinst = fs_to_install;
1549  
1550 --- /dev/null
1551 +++ b/fs/yaffs2/yaffs_getblockinfo.h
1552 @@ -0,0 +1,34 @@
1553 +/*
1554 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
1555 + *
1556 + * Copyright (C) 2002-2007 Aleph One Ltd.
1557 + *   for Toby Churchill Ltd and Brightstar Engineering
1558 + *
1559 + * Created by Charles Manning <charles@aleph1.co.uk>
1560 + *
1561 + * This program is free software; you can redistribute it and/or modify
1562 + * it under the terms of the GNU Lesser General Public License version 2.1 as
1563 + * published by the Free Software Foundation.
1564 + *
1565 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
1566 + */
1567 +
1568 +#ifndef __YAFFS_GETBLOCKINFO_H__
1569 +#define __YAFFS_GETBLOCKINFO_H__
1570 +
1571 +#include "yaffs_guts.h"
1572 +
1573 +/* Function to manipulate block info */
1574 +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
1575 +{
1576 +       if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
1577 +               T(YAFFS_TRACE_ERROR,
1578 +                 (TSTR
1579 +                  ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
1580 +                  blk));
1581 +               YBUG();
1582 +       }
1583 +       return &dev->blockInfo[blk - dev->internalStartBlock];
1584 +}
1585 +
1586 +#endif
1587 --- a/fs/yaffs2/yaffs_nand.c
1588 +++ b/fs/yaffs2/yaffs_nand.c
1589 @@ -12,12 +12,13 @@
1590   */
1591  
1592  const char *yaffs_nand_c_version =
1593 -    "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $";
1594 +    "$Id: yaffs_nand.c,v 1.9 2008-05-05 07:58:58 charles Exp $";
1595  
1596  #include "yaffs_nand.h"
1597  #include "yaffs_tagscompat.h"
1598  #include "yaffs_tagsvalidity.h"
1599  
1600 +#include "yaffs_getblockinfo.h"
1601  
1602  int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
1603                                            __u8 * buffer,
1604 @@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * de
1605  int yaffs_QueryInitialBlockState(yaffs_Device * dev,
1606                                                  int blockNo,
1607                                                  yaffs_BlockState * state,
1608 -                                                unsigned *sequenceNumber)
1609 +                                                __u32 *sequenceNumber)
1610  {
1611         blockNo -= dev->blockOffset;
1612  
1613 --- a/fs/yaffs2/yaffs_guts.c
1614 +++ b/fs/yaffs2/yaffs_guts.c
1615 @@ -11,14 +11,16 @@
1616   * published by the Free Software Foundation.
1617   */
1618  
1619 +
1620  const char *yaffs_guts_c_version =
1621 -    "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $";
1622 +    "$Id: yaffs_guts.c,v 1.76 2009-01-23 06:36:49 charles Exp $";
1623  
1624  #include "yportenv.h"
1625  
1626  #include "yaffsinterface.h"
1627  #include "yaffs_guts.h"
1628  #include "yaffs_tagsvalidity.h"
1629 +#include "yaffs_getblockinfo.h"
1630  
1631  #include "yaffs_tagscompat.h"
1632  #ifndef  CONFIG_YAFFS_USE_OWN_SORT
1633 @@ -32,11 +34,6 @@ const char *yaffs_guts_c_version =
1634  #include "yaffs_packedtags2.h"
1635  
1636  
1637 -#ifdef CONFIG_YAFFS_WINCE
1638 -void yfsd_LockYAFFS(BOOL fsLockOnly);
1639 -void yfsd_UnlockYAFFS(BOOL fsLockOnly);
1640 -#endif
1641 -
1642  #define YAFFS_PASSIVE_GC_CHUNKS 2
1643  
1644  #include "yaffs_ecc.h"
1645 @@ -78,9 +75,6 @@ static int yaffs_DoGenericObjectDeletion
1646  
1647  static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
1648  
1649 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
1650 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1651 -                                   int lineNo);
1652  
1653  static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
1654                                   int chunkInNAND);
1655 @@ -99,6 +93,7 @@ static void yaffs_VerifyFreeChunks(yaffs
1656  
1657  static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
1658  
1659 +static void yaffs_VerifyDirectory(yaffs_Object *directory);
1660  #ifdef YAFFS_PARANOID
1661  static int yaffs_CheckFileSanity(yaffs_Object * in);
1662  #else
1663 @@ -121,95 +116,109 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
1664  
1665  /* Function to calculate chunk and offset */
1666  
1667 -static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
1668 +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
1669  {
1670 -       if(dev->chunkShift){
1671 -               /* Easy-peasy power of 2 case */
1672 -               *chunk  = (__u32)(addr >> dev->chunkShift);
1673 -               *offset = (__u32)(addr & dev->chunkMask);
1674 -       }
1675 -       else if(dev->crumbsPerChunk)
1676 +       int chunk;
1677 +       __u32 offset;
1678 +       
1679 +       chunk  = (__u32)(addr >> dev->chunkShift);
1680 +               
1681 +       if(dev->chunkDiv == 1)
1682         {
1683 -               /* Case where we're using "crumbs" */
1684 -               *offset = (__u32)(addr & dev->crumbMask);
1685 -               addr >>= dev->crumbShift;
1686 -               *chunk = ((__u32)addr)/dev->crumbsPerChunk;
1687 -               *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
1688 +               /* easy power of 2 case */
1689 +               offset = (__u32)(addr & dev->chunkMask);
1690         }
1691         else
1692 -               YBUG();
1693 +       {
1694 +               /* Non power-of-2 case */
1695 +               
1696 +               loff_t chunkBase;
1697 +               
1698 +               chunk /= dev->chunkDiv;
1699 +               
1700 +               chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
1701 +               offset = (__u32)(addr - chunkBase);
1702 +       }
1703 +
1704 +       *chunkOut = chunk;
1705 +       *offsetOut = offset;
1706  }
1707  
1708 -/* Function to return the number of shifts for a power of 2 greater than or equal
1709 +/* Function to return the number of shifts for a power of 2 greater than or equal 
1710   * to the given number
1711   * Note we don't try to cater for all possible numbers and this does not have to
1712   * be hellishly efficient.
1713   */
1714 -
1715
1716  static __u32 ShiftsGE(__u32 x)
1717  {
1718         int extraBits;
1719         int nShifts;
1720 -
1721 +       
1722         nShifts = extraBits = 0;
1723 -
1724 +       
1725         while(x>1){
1726                 if(x & 1) extraBits++;
1727                 x>>=1;
1728                 nShifts++;
1729         }
1730  
1731 -       if(extraBits)
1732 +       if(extraBits) 
1733                 nShifts++;
1734 -
1735 +               
1736         return nShifts;
1737  }
1738  
1739  /* Function to return the number of shifts to get a 1 in bit 0
1740   */
1741 -
1742 -static __u32 ShiftDiv(__u32 x)
1743
1744 +static __u32 Shifts(__u32 x)
1745  {
1746         int nShifts;
1747 -
1748 +       
1749         nShifts =  0;
1750 -
1751 +       
1752         if(!x) return 0;
1753 -
1754 +       
1755         while( !(x&1)){
1756                 x>>=1;
1757                 nShifts++;
1758         }
1759 -
1760 +               
1761         return nShifts;
1762  }
1763  
1764  
1765  
1766 -/*
1767 +/* 
1768   * Temporary buffer manipulations.
1769   */
1770  
1771 -static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
1772 +static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)      
1773  {
1774         int i;
1775         __u8 *buf = (__u8 *)1;
1776 -
1777 +               
1778         memset(dev->tempBuffer,0,sizeof(dev->tempBuffer));
1779 -
1780 +               
1781         for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
1782                 dev->tempBuffer[i].line = 0;    /* not in use */
1783                 dev->tempBuffer[i].buffer = buf =
1784 -                   YMALLOC_DMA(dev->nDataBytesPerChunk);
1785 +                   YMALLOC_DMA(dev->totalBytesPerChunk);
1786         }
1787 -
1788 +               
1789         return buf ? YAFFS_OK : YAFFS_FAIL;
1790 -
1791 +       
1792  }
1793  
1794 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
1795 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
1796  {
1797         int i, j;
1798 +
1799 +       dev->tempInUse++;
1800 +       if(dev->tempInUse > dev->maxTemp)
1801 +               dev->maxTemp = dev->tempInUse;
1802 +
1803         for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
1804                 if (dev->tempBuffer[i].line == 0) {
1805                         dev->tempBuffer[i].line = lineNo;
1806 @@ -242,10 +251,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D
1807  
1808  }
1809  
1810 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1811 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1812                                     int lineNo)
1813  {
1814         int i;
1815 +       
1816 +       dev->tempInUse--;
1817 +       
1818         for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
1819                 if (dev->tempBuffer[i].buffer == buffer) {
1820                         dev->tempBuffer[i].line = 0;
1821 @@ -337,7 +349,7 @@ static Y_INLINE void yaffs_ClearChunkBit
1822  static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
1823  {
1824         __u8 *blkBits = yaffs_BlockBits(dev, blk);
1825 -
1826 +       
1827         yaffs_VerifyChunkBitId(dev,blk,chunk);
1828  
1829         blkBits[chunk / 8] |= (1 << (chunk & 7));
1830 @@ -375,16 +387,16 @@ static int yaffs_CountChunkBits(yaffs_De
1831                                 n++;
1832                         x >>=1;
1833                 }
1834 -
1835 +                       
1836                 blkBits++;
1837         }
1838         return n;
1839  }
1840  
1841 -/*
1842 +/* 
1843   * Verification code
1844   */
1845 -
1846
1847  static int yaffs_SkipVerification(yaffs_Device *dev)
1848  {
1849         return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
1850 @@ -417,14 +429,14 @@ static void yaffs_VerifyBlock(yaffs_Devi
1851  {
1852         int actuallyUsed;
1853         int inUse;
1854 -
1855 +       
1856         if(yaffs_SkipVerification(dev))
1857                 return;
1858 -
1859 +               
1860         /* Report illegal runtime states */
1861 -       if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
1862 +       if(bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
1863                 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState));
1864 -
1865 +               
1866         switch(bi->blockState){
1867          case YAFFS_BLOCK_STATE_UNKNOWN:
1868          case YAFFS_BLOCK_STATE_SCANNING:
1869 @@ -432,43 +444,44 @@ static void yaffs_VerifyBlock(yaffs_Devi
1870                 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR),
1871                 n,blockStateName[bi->blockState]));
1872         }
1873 -
1874 +       
1875         /* Check pages in use and soft deletions are legal */
1876 -
1877 +       
1878         actuallyUsed = bi->pagesInUse - bi->softDeletions;
1879 -
1880 +       
1881         if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock ||
1882            bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock ||
1883            actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock)
1884                 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR),
1885                 n,bi->pagesInUse,bi->softDeletions));
1886 -
1887 -
1888 +       
1889 +               
1890         /* Check chunk bitmap legal */
1891         inUse = yaffs_CountChunkBits(dev,n);
1892         if(inUse != bi->pagesInUse)
1893                 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR),
1894                         n,bi->pagesInUse,inUse));
1895 -
1896 +       
1897         /* Check that the sequence number is valid.
1898 -        * Ten million is legal, but is very unlikely
1899 +        * Ten million is legal, but is very unlikely 
1900          */
1901 -       if(dev->isYaffs2 &&
1902 +       if(dev->isYaffs2 && 
1903            (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) &&
1904            (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 ))
1905                 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR),
1906                 n,bi->sequenceNumber));
1907 -
1908 +               
1909  }
1910  
1911  static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
1912  {
1913         yaffs_VerifyBlock(dev,bi,n);
1914 -
1915 +       
1916         /* After collection the block should be in the erased state */
1917 -       /* TODO: This will need to change if we do partial gc */
1918 -
1919 -       if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
1920 +       /* This will need to change if we do partial gc */
1921 +       
1922 +       if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING &&
1923 +          bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
1924                 T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR),
1925                         n,bi->blockState));
1926         }
1927 @@ -479,28 +492,28 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1928         int i;
1929         int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
1930         int nIllegalBlockStates = 0;
1931 -
1932 +       
1933  
1934         if(yaffs_SkipVerification(dev))
1935                 return;
1936  
1937         memset(nBlocksPerState,0,sizeof(nBlocksPerState));
1938  
1939 -
1940 +               
1941         for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){
1942                 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
1943                 yaffs_VerifyBlock(dev,bi,i);
1944  
1945 -               if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
1946 +               if(bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
1947                         nBlocksPerState[bi->blockState]++;
1948                 else
1949                         nIllegalBlockStates++;
1950 -
1951 +                                       
1952         }
1953 -
1954 +       
1955         T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
1956         T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR)));
1957 -
1958 +       
1959         T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates));
1960         if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
1961                 T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR)));
1962 @@ -509,17 +522,17 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1963                 T(YAFFS_TRACE_VERIFY,
1964                   (TSTR("%s %d blocks"TENDSTR),
1965                   blockStateName[i],nBlocksPerState[i]));
1966 -
1967 +       
1968         if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])
1969                 T(YAFFS_TRACE_VERIFY,
1970                  (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),
1971                  dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]));
1972 -
1973 +                
1974         if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])
1975                 T(YAFFS_TRACE_VERIFY,
1976                  (TSTR("Erased block count wrong dev %d count %d"TENDSTR),
1977                  dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]));
1978 -
1979 +                
1980         if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)
1981                 T(YAFFS_TRACE_VERIFY,
1982                  (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),
1983 @@ -535,16 +548,16 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1984   */
1985  static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
1986  {
1987 -       if(yaffs_SkipVerification(obj->myDev))
1988 +       if(obj && yaffs_SkipVerification(obj->myDev))
1989                 return;
1990 -
1991 +               
1992         if(!(tags && obj && oh)){
1993                 T(YAFFS_TRACE_VERIFY,
1994                                 (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR),
1995                                 (__u32)tags,(__u32)obj,(__u32)oh));
1996                 return;
1997         }
1998 -
1999 +       
2000         if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
2001            oh->type > YAFFS_OBJECT_TYPE_MAX)
2002                 T(YAFFS_TRACE_VERIFY,
2003 @@ -559,25 +572,25 @@ static void yaffs_VerifyObjectHeader(yaf
2004  
2005         /*
2006          * Check that the object's parent ids match if parentCheck requested.
2007 -        *
2008 +        * 
2009          * Tests do not apply to the root object.
2010          */
2011 -
2012 +       
2013         if(parentCheck && tags->objectId > 1 && !obj->parent)
2014                 T(YAFFS_TRACE_VERIFY,
2015                  (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),
2016                  tags->objectId, oh->parentObjectId));
2017 -
2018 -
2019 +               
2020 +       
2021         if(parentCheck && obj->parent &&
2022 -          oh->parentObjectId != obj->parent->objectId &&
2023 +          oh->parentObjectId != obj->parent->objectId && 
2024            (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||
2025             obj->parent->objectId != YAFFS_OBJECTID_DELETED))
2026                 T(YAFFS_TRACE_VERIFY,
2027                  (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),
2028                  tags->objectId, oh->parentObjectId, obj->parent->objectId));
2029 -
2030 -
2031 +               
2032 +       
2033         if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */
2034                 T(YAFFS_TRACE_VERIFY,
2035                 (TSTR("Obj %d header name is NULL"TENDSTR),
2036 @@ -597,7 +610,6 @@ static int yaffs_VerifyTnodeWorker(yaffs
2037         int i;
2038         yaffs_Device *dev = obj->myDev;
2039         int ok = 1;
2040 -       int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2041  
2042         if (tn) {
2043                 if (level > 0) {
2044 @@ -611,15 +623,14 @@ static int yaffs_VerifyTnodeWorker(yaffs
2045                                 }
2046                         }
2047                 } else if (level == 0) {
2048 -                       int i;
2049                         yaffs_ExtendedTags tags;
2050                         __u32 objectId = obj->objectId;
2051 -
2052 +                       
2053                         chunkOffset <<=  YAFFS_TNODES_LEVEL0_BITS;
2054 -
2055 +                       
2056                         for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
2057                                 __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2058 -
2059 +                               
2060                                 if(theChunk > 0){
2061                                         /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
2062                                         yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
2063 @@ -646,18 +657,20 @@ static void yaffs_VerifyFile(yaffs_Objec
2064         __u32 lastChunk;
2065         __u32 x;
2066         __u32 i;
2067 -       int ok;
2068         yaffs_Device *dev;
2069         yaffs_ExtendedTags tags;
2070         yaffs_Tnode *tn;
2071         __u32 objectId;
2072 -
2073 -       if(obj && yaffs_SkipVerification(obj->myDev))
2074 +       
2075 +       if(!obj)
2076                 return;
2077  
2078 +       if(yaffs_SkipVerification(obj->myDev))
2079 +               return;
2080 +       
2081         dev = obj->myDev;
2082         objectId = obj->objectId;
2083 -
2084 +       
2085         /* Check file size is consistent with tnode depth */
2086         lastChunk =  obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;
2087         x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;
2088 @@ -666,23 +679,23 @@ static void yaffs_VerifyFile(yaffs_Objec
2089                 x >>= YAFFS_TNODES_INTERNAL_BITS;
2090                 requiredTallness++;
2091         }
2092 -
2093 +       
2094         actualTallness = obj->variant.fileVariant.topLevel;
2095 -
2096 +       
2097         if(requiredTallness > actualTallness )
2098                 T(YAFFS_TRACE_VERIFY,
2099                 (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),
2100                  obj->objectId,actualTallness, requiredTallness));
2101 -
2102 -
2103 -       /* Check that the chunks in the tnode tree are all correct.
2104 +       
2105 +       
2106 +       /* Check that the chunks in the tnode tree are all correct. 
2107          * We do this by scanning through the tnode tree and
2108          * checking the tags for every chunk match.
2109          */
2110  
2111         if(yaffs_SkipNANDVerification(dev))
2112                 return;
2113 -
2114 +               
2115         for(i = 1; i <= lastChunk; i++){
2116                 tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i);
2117  
2118 @@ -703,18 +716,12 @@ static void yaffs_VerifyFile(yaffs_Objec
2119  
2120  }
2121  
2122 -static void yaffs_VerifyDirectory(yaffs_Object *obj)
2123 -{
2124 -       if(obj && yaffs_SkipVerification(obj->myDev))
2125 -               return;
2126 -
2127 -}
2128  
2129  static void yaffs_VerifyHardLink(yaffs_Object *obj)
2130  {
2131         if(obj && yaffs_SkipVerification(obj->myDev))
2132                 return;
2133 -
2134 +               
2135         /* Verify sane equivalent object */
2136  }
2137  
2138 @@ -722,7 +729,7 @@ static void yaffs_VerifySymlink(yaffs_Ob
2139  {
2140         if(obj && yaffs_SkipVerification(obj->myDev))
2141                 return;
2142 -
2143 +               
2144         /* Verify symlink string */
2145  }
2146  
2147 @@ -735,69 +742,77 @@ static void yaffs_VerifySpecial(yaffs_Ob
2148  static void yaffs_VerifyObject(yaffs_Object *obj)
2149  {
2150         yaffs_Device *dev;
2151 -
2152 +       
2153         __u32 chunkMin;
2154         __u32 chunkMax;
2155 -
2156 +       
2157         __u32 chunkIdOk;
2158 -       __u32 chunkIsLive;
2159 -
2160 +       __u32 chunkInRange;
2161 +       __u32 chunkShouldNotBeDeleted;
2162 +       __u32 chunkValid; 
2163 +       
2164         if(!obj)
2165                 return;
2166 -
2167 +               
2168 +       if(obj->beingCreated)
2169 +               return;
2170 +       
2171         dev = obj->myDev;
2172 -
2173 +       
2174         if(yaffs_SkipVerification(dev))
2175                 return;
2176 -
2177 +               
2178         /* Check sane object header chunk */
2179  
2180         chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
2181         chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
2182  
2183 -       chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax);
2184 -       chunkIsLive = chunkIdOk &&
2185 +       chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
2186 +       chunkIdOk = chunkInRange || obj->hdrChunk == 0;
2187 +       chunkValid  =  chunkInRange &&
2188                         yaffs_CheckChunkBit(dev,
2189 -                                           obj->chunkId / dev->nChunksPerBlock,
2190 -                                           obj->chunkId % dev->nChunksPerBlock);
2191 +                                           obj->hdrChunk / dev->nChunksPerBlock,
2192 +                                           obj->hdrChunk % dev->nChunksPerBlock);
2193 +       chunkShouldNotBeDeleted = chunkInRange && !chunkValid;
2194 +
2195         if(!obj->fake &&
2196 -           (!chunkIdOk || !chunkIsLive)) {
2197 +           (!chunkIdOk || chunkShouldNotBeDeleted)) {
2198            T(YAFFS_TRACE_VERIFY,
2199            (TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
2200 -          obj->objectId,obj->chunkId,
2201 +          obj->objectId,obj->hdrChunk,
2202            chunkIdOk ? "" : ",out of range",
2203 -          chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
2204 +          chunkShouldNotBeDeleted ? ",marked as deleted" : ""));
2205         }
2206 -
2207 -       if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
2208 +       
2209 +       if(chunkValid &&!yaffs_SkipNANDVerification(dev)) {
2210                 yaffs_ExtendedTags tags;
2211                 yaffs_ObjectHeader *oh;
2212                 __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
2213 -
2214 +               
2215                 oh = (yaffs_ObjectHeader *)buffer;
2216  
2217 -               yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
2218 +               yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags);
2219  
2220                 yaffs_VerifyObjectHeader(obj,oh,&tags,1);
2221 -
2222 +               
2223                 yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
2224         }
2225 -
2226 +       
2227         /* Verify it has a parent */
2228         if(obj && !obj->fake &&
2229            (!obj->parent || obj->parent->myDev != dev)){
2230            T(YAFFS_TRACE_VERIFY,
2231            (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),
2232 -          obj->objectId,obj->parent));
2233 +          obj->objectId,obj->parent));    
2234         }
2235 -
2236 +       
2237         /* Verify parent is a directory */
2238         if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
2239            T(YAFFS_TRACE_VERIFY,
2240            (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),
2241 -          obj->objectId,obj->parent->variantType));
2242 +          obj->objectId,obj->parent->variantType));       
2243         }
2244 -
2245 +       
2246         switch(obj->variantType){
2247         case YAFFS_OBJECT_TYPE_FILE:
2248                 yaffs_VerifyFile(obj);
2249 @@ -818,31 +833,31 @@ static void yaffs_VerifyObject(yaffs_Obj
2250         default:
2251                 T(YAFFS_TRACE_VERIFY,
2252                 (TSTR("Obj %d has illegaltype %d"TENDSTR),
2253 -               obj->objectId,obj->variantType));
2254 +               obj->objectId,obj->variantType));          
2255                 break;
2256         }
2257 -
2258 -
2259 +       
2260 +       
2261  }
2262  
2263  static void yaffs_VerifyObjects(yaffs_Device *dev)
2264  {
2265 -       yaffs_Object *obj;
2266 -       int i;
2267 -       struct list_head *lh;
2268 -
2269 -       if(yaffs_SkipVerification(dev))
2270 -               return;
2271 -
2272 -       /* Iterate through the objects in each hash entry */
2273 -
2274 -        for(i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++){
2275 -               list_for_each(lh, &dev->objectBucket[i].list) {
2276 -                       if (lh) {
2277 -                               obj = list_entry(lh, yaffs_Object, hashLink);
2278 -                               yaffs_VerifyObject(obj);
2279 -                       }
2280 -               }
2281 +        yaffs_Object *obj;
2282 +        int i;
2283 +        struct ylist_head *lh;
2284 +
2285 +        if(yaffs_SkipVerification(dev))
2286 +                return;
2287 +       
2288 +        /* Iterate through the objects in each hash entry */
2289 +         
2290 +         for(i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++){
2291 +                ylist_for_each(lh, &dev->objectBucket[i].list) {
2292 +                        if (lh) {
2293 +                                obj = ylist_entry(lh, yaffs_Object, hashLink);
2294 +                                yaffs_VerifyObject(obj);
2295 +                        }
2296 +                }
2297          }
2298  
2299  }
2300 @@ -851,7 +866,7 @@ static void yaffs_VerifyObjects(yaffs_De
2301  /*
2302   *  Simple hash function. Needs to have a reasonable spread
2303   */
2304 -
2305
2306  static Y_INLINE int yaffs_HashFunction(int n)
2307  {
2308         n = abs(n);
2309 @@ -859,9 +874,10 @@ static Y_INLINE int yaffs_HashFunction(i
2310  }
2311  
2312  /*
2313 - * Access functions to useful fake objects
2314 + * Access functions to useful fake objects.
2315 + * Note that root might have a presence in NAND if permissions are set.
2316   */
2317 -
2318
2319  yaffs_Object *yaffs_Root(yaffs_Device * dev)
2320  {
2321         return dev->rootDir;
2322 @@ -876,7 +892,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Dev
2323  /*
2324   *  Erased NAND checking functions
2325   */
2326 -
2327
2328  int yaffs_CheckFF(__u8 * buffer, int nBytes)
2329  {
2330         /* Horrible, slow implementation */
2331 @@ -898,10 +914,10 @@ static int yaffs_CheckChunkErased(struct
2332         int result;
2333  
2334         result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
2335 -
2336 +       
2337         if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
2338                 retval = YAFFS_FAIL;
2339 -
2340 +               
2341  
2342         if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
2343                 T(YAFFS_TRACE_NANDACCESS,
2344 @@ -915,7 +931,6 @@ static int yaffs_CheckChunkErased(struct
2345  
2346  }
2347  
2348 -
2349  static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
2350                                              const __u8 * data,
2351                                              yaffs_ExtendedTags * tags,
2352 @@ -992,7 +1007,11 @@ static int yaffs_WriteNewChunkWithTagsTo
2353                 /* Copy the data into the robustification buffer */
2354                 yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
2355  
2356 -       } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts);
2357 +       } while (writeOk != YAFFS_OK && 
2358 +               (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
2359 +       
2360 +       if(!writeOk)
2361 +               chunk = -1;
2362  
2363         if (attempts > 1) {
2364                 T(YAFFS_TRACE_ERROR,
2365 @@ -1008,13 +1027,13 @@ static int yaffs_WriteNewChunkWithTagsTo
2366  /*
2367   * Block retiring for handling a broken block.
2368   */
2369 -
2370
2371  static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
2372  {
2373         yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2374  
2375         yaffs_InvalidateCheckpoint(dev);
2376 -
2377 +       
2378         yaffs_MarkBlockBad(dev, blockInNAND);
2379  
2380         bi->blockState = YAFFS_BLOCK_STATE_DEAD;
2381 @@ -1028,7 +1047,7 @@ static void yaffs_RetireBlock(yaffs_Devi
2382   * Functions for robustisizing TODO
2383   *
2384   */
2385 -
2386
2387  static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
2388                                      const __u8 * data,
2389                                      const yaffs_ExtendedTags * tags)
2390 @@ -1046,13 +1065,13 @@ void yaffs_HandleChunkError(yaffs_Device
2391                 bi->gcPrioritise = 1;
2392                 dev->hasPendingPrioritisedGCs = 1;
2393                 bi->chunkErrorStrikes ++;
2394 -
2395 +               
2396                 if(bi->chunkErrorStrikes > 3){
2397                         bi->needsRetiring = 1; /* Too many stikes, so retire this */
2398                         T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
2399  
2400                 }
2401 -
2402 +               
2403         }
2404  }
2405  
2406 @@ -1063,30 +1082,30 @@ static void yaffs_HandleWriteChunkError(
2407         yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2408  
2409         yaffs_HandleChunkError(dev,bi);
2410 -
2411 -
2412 +               
2413 +       
2414         if(erasedOk ) {
2415                 /* Was an actual write failure, so mark the block for retirement  */
2416                 bi->needsRetiring = 1;
2417                 T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
2418                   (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
2419  
2420 -
2421 +               
2422         }
2423 -
2424 +       
2425         /* Delete the chunk */
2426         yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
2427  }
2428  
2429  
2430 -/*---------------- Name handling functions ------------*/
2431 +/*---------------- Name handling functions ------------*/ 
2432  
2433  static __u16 yaffs_CalcNameSum(const YCHAR * name)
2434  {
2435         __u16 sum = 0;
2436         __u16 i = 1;
2437  
2438 -       YUCHAR *bname = (YUCHAR *) name;
2439 +       const YUCHAR *bname = (const YUCHAR *) name;
2440         if (bname) {
2441                 while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
2442  
2443 @@ -1099,12 +1118,14 @@ static __u16 yaffs_CalcNameSum(const YCH
2444                         bname++;
2445                 }
2446         }
2447 +       
2448         return sum;
2449  }
2450  
2451  static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
2452  {
2453  #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
2454 +       memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); 
2455         if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
2456                 yaffs_strcpy(obj->shortName, name);
2457         } else {
2458 @@ -1120,7 +1141,7 @@ static void yaffs_SetObjectName(yaffs_Ob
2459   * The list is hooked together using the first pointer
2460   * in the tnode.
2461   */
2462 -
2463
2464  /* yaffs_CreateTnodes creates a bunch more tnodes and
2465   * adds them to the tnode free list.
2466   * Don't use this function directly
2467 @@ -1138,11 +1159,15 @@ static int yaffs_CreateTnodes(yaffs_Devi
2468  
2469         if (nTnodes < 1)
2470                 return YAFFS_OK;
2471 -
2472 +               
2473         /* Calculate the tnode size in bytes for variable width tnode support.
2474          * Must be a multiple of 32-bits  */
2475         tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2476  
2477 +       if(tnodeSize < sizeof(yaffs_Tnode))
2478 +               tnodeSize = sizeof(yaffs_Tnode);
2479 +               
2480 +
2481         /* make these things */
2482  
2483         newTnodes = YMALLOC(nTnodes * tnodeSize);
2484 @@ -1175,7 +1200,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
2485                 next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
2486                 curr->internal[0] = next;
2487         }
2488 -
2489 +       
2490         curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
2491         curr->internal[0] = dev->freeTnodes;
2492         dev->freeTnodes = (yaffs_Tnode *)mem;
2493 @@ -1190,7 +1215,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
2494          * NB If we can't add this to the management list it isn't fatal
2495          * but it just means we can't free this bunch of tnodes later.
2496          */
2497 -
2498 +        
2499         tnl = YMALLOC(sizeof(yaffs_TnodeList));
2500         if (!tnl) {
2501                 T(YAFFS_TRACE_ERROR,
2502 @@ -1233,17 +1258,23 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya
2503                 dev->nFreeTnodes--;
2504         }
2505  
2506 +       dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2507 +
2508         return tn;
2509  }
2510  
2511  static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
2512  {
2513         yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
2514 +       int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2515  
2516 +       if(tnodeSize < sizeof(yaffs_Tnode))
2517 +               tnodeSize = sizeof(yaffs_Tnode);
2518 +       
2519         if(tn)
2520 -               memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
2521 +               memset(tn, 0, tnodeSize);
2522  
2523 -       return tn;
2524 +       return tn;      
2525  }
2526  
2527  /* FreeTnode frees up a tnode and puts it back on the free list */
2528 @@ -1262,6 +1293,8 @@ static void yaffs_FreeTnode(yaffs_Device
2529                 dev->freeTnodes = tn;
2530                 dev->nFreeTnodes++;
2531         }
2532 +       dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2533 +       
2534  }
2535  
2536  static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
2537 @@ -1299,19 +1332,19 @@ void yaffs_PutLevel0Tnode(yaffs_Device *
2538    __u32 bitInWord;
2539    __u32 wordInMap;
2540    __u32 mask;
2541 -
2542 +  
2543    pos &= YAFFS_TNODES_LEVEL0_MASK;
2544    val >>= dev->chunkGroupBits;
2545 -
2546 +  
2547    bitInMap = pos * dev->tnodeWidth;
2548    wordInMap = bitInMap /32;
2549    bitInWord = bitInMap & (32 -1);
2550 -
2551 +  
2552    mask = dev->tnodeMask << bitInWord;
2553 -
2554 +  
2555    map[wordInMap] &= ~mask;
2556    map[wordInMap] |= (mask & (val << bitInWord));
2557 -
2558 +  
2559    if(dev->tnodeWidth > (32-bitInWord)) {
2560      bitInWord = (32 - bitInWord);
2561      wordInMap++;;
2562 @@ -1328,24 +1361,24 @@ static __u32 yaffs_GetChunkGroupBase(yaf
2563    __u32 bitInWord;
2564    __u32 wordInMap;
2565    __u32 val;
2566 -
2567 +  
2568    pos &= YAFFS_TNODES_LEVEL0_MASK;
2569 -
2570 +  
2571    bitInMap = pos * dev->tnodeWidth;
2572    wordInMap = bitInMap /32;
2573    bitInWord = bitInMap & (32 -1);
2574 -
2575 +  
2576    val = map[wordInMap] >> bitInWord;
2577 -
2578 +  
2579    if(dev->tnodeWidth > (32-bitInWord)) {
2580      bitInWord = (32 - bitInWord);
2581      wordInMap++;;
2582      val |= (map[wordInMap] << bitInWord);
2583    }
2584 -
2585 +  
2586    val &= dev->tnodeMask;
2587    val <<= dev->chunkGroupBits;
2588 -
2589 +  
2590    return val;
2591  }
2592  
2593 @@ -1394,7 +1427,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
2594         while (level > 0 && tn) {
2595                 tn = tn->
2596                     internal[(chunkId >>
2597 -                              ( YAFFS_TNODES_LEVEL0_BITS +
2598 +                              ( YAFFS_TNODES_LEVEL0_BITS + 
2599                                  (level - 1) *
2600                                  YAFFS_TNODES_INTERNAL_BITS)
2601                               ) &
2602 @@ -1416,7 +1449,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
2603   *  If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
2604   *  be plugged into the ttree.
2605   */
2606 -
2607
2608  static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
2609                                                yaffs_FileStructure * fStruct,
2610                                                __u32 chunkId,
2611 @@ -1453,7 +1486,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2612         if (requiredTallness > fStruct->topLevel) {
2613                 /* Not tall enough,gotta make the tree taller */
2614                 for (i = fStruct->topLevel; i < requiredTallness; i++) {
2615 -
2616 +               
2617                         tn = yaffs_GetTnode(dev);
2618  
2619                         if (tn) {
2620 @@ -1472,7 +1505,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2621  
2622         l = fStruct->topLevel;
2623         tn = fStruct->top;
2624 -
2625 +       
2626         if(l > 0) {
2627                 while (l > 0 && tn) {
2628                         x = (chunkId >>
2629 @@ -1492,13 +1525,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2630                                         if(tn->internal[x])
2631                                                 yaffs_FreeTnode(dev,tn->internal[x]);
2632                                         tn->internal[x] = passedTn;
2633 -
2634 +                       
2635                                 } else if(!tn->internal[x]) {
2636                                         /* Don't have one, none passed in */
2637                                         tn->internal[x] = yaffs_GetTnode(dev);
2638                                 }
2639                         }
2640 -
2641 +               
2642                         tn = tn->internal[x];
2643                         l--;
2644                 }
2645 @@ -1539,7 +1572,7 @@ static int yaffs_FindChunkInGroup(yaffs_
2646  
2647  /* DeleteWorker scans backwards through the tnode tree and deletes all the
2648   * chunks and tnodes in the file
2649 - * Returns 1 if the tree was deleted.
2650 + * Returns 1 if the tree was deleted. 
2651   * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
2652   */
2653  
2654 @@ -1653,7 +1686,7 @@ static void yaffs_SoftDeleteChunk(yaffs_
2655   * of the tnode.
2656   * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
2657   */
2658 -
2659
2660  static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
2661                                   __u32 level, int chunkOffset)
2662  {
2663 @@ -1694,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_
2664                                 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2665                                 if (theChunk) {
2666                                         /* Note this does not find the real chunk, only the chunk group.
2667 -                                        * We make an assumption that a chunk group is not larger than
2668 +                                        * We make an assumption that a chunk group is not larger than 
2669                                          * a block.
2670                                          */
2671                                         yaffs_SoftDeleteChunk(dev, theChunk);
2672 @@ -1796,7 +1829,7 @@ static int yaffs_PruneFileStructure(yaff
2673                 /* Now we have a tree with all the non-zero branches NULL but the height
2674                  * is the same as it was.
2675                  * Let's see if we can trim internal tnodes to shorten the tree.
2676 -                * We can do this if only the 0th element in the tnode is in use
2677 +                * We can do this if only the 0th element in the tnode is in use 
2678                  * (ie all the non-zero are NULL)
2679                  */
2680  
2681 @@ -1850,14 +1883,14 @@ static int yaffs_CreateFreeObjects(yaffs
2682                   (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
2683                 return YAFFS_FAIL;
2684         }
2685 +       
2686 +        /* Hook them into the free list */
2687 +        for (i = 0; i < nObjects - 1; i++) {
2688 +                newObjects[i].siblings.next =
2689 +                    (struct ylist_head *)(&newObjects[i + 1]);
2690 +        }
2691  
2692 -       /* Hook them into the free list */
2693 -       for (i = 0; i < nObjects - 1; i++) {
2694 -               newObjects[i].siblings.next =
2695 -                   (struct list_head *)(&newObjects[i + 1]);
2696 -       }
2697 -
2698 -       newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
2699 +        newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
2700         dev->freeObjects = newObjects;
2701         dev->nFreeObjects += nObjects;
2702         dev->nObjectsCreated += nObjects;
2703 @@ -1877,6 +1910,9 @@ static yaffs_Object *yaffs_AllocateEmpty
2704  {
2705         yaffs_Object *tn = NULL;
2706  
2707 +#ifdef VALGRIND_TEST
2708 +       tn = YMALLOC(sizeof(yaffs_Object));
2709 +#else
2710         /* If there are none left make more */
2711         if (!dev->freeObjects) {
2712                 yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
2713 @@ -1887,25 +1923,40 @@ static yaffs_Object *yaffs_AllocateEmpty
2714                 dev->freeObjects =
2715                     (yaffs_Object *) (dev->freeObjects->siblings.next);
2716                 dev->nFreeObjects--;
2717 -
2718 +       }
2719 +#endif
2720 +       if(tn){
2721                 /* Now sweeten it up... */
2722  
2723                 memset(tn, 0, sizeof(yaffs_Object));
2724 +               tn->beingCreated = 1;
2725 +               
2726                 tn->myDev = dev;
2727 -               tn->chunkId = -1;
2728 +               tn->hdrChunk = 0;
2729                 tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
2730 -               INIT_LIST_HEAD(&(tn->hardLinks));
2731 -               INIT_LIST_HEAD(&(tn->hashLink));
2732 -               INIT_LIST_HEAD(&tn->siblings);
2733 +               YINIT_LIST_HEAD(&(tn->hardLinks));
2734 +               YINIT_LIST_HEAD(&(tn->hashLink));
2735 +               YINIT_LIST_HEAD(&tn->siblings);
2736 +               
2737 +
2738 +               /* Now make the directory sane */
2739 +               if(dev->rootDir){
2740 +                       tn->parent = dev->rootDir;
2741 +                       ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children);
2742 +               }
2743  
2744 -               /* Add it to the lost and found directory.
2745 -                * NB Can't put root or lostNFound in lostNFound so
2746 +                /* Add it to the lost and found directory.
2747 +                 * NB Can't put root or lostNFound in lostNFound so
2748                  * check if lostNFound exists first
2749                  */
2750                 if (dev->lostNFoundDir) {
2751                         yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
2752                 }
2753 +               
2754 +               tn->beingCreated = 0;
2755         }
2756 +       
2757 +       dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2758  
2759         return tn;
2760  }
2761 @@ -1917,14 +1968,14 @@ static yaffs_Object *yaffs_CreateFakeDir
2762         yaffs_Object *obj =
2763             yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
2764         if (obj) {
2765 -               obj->fake = 1;          /* it is fake so it has no NAND presence... */
2766 +               obj->fake = 1;          /* it is fake so it might have no NAND presence... */
2767                 obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
2768                 obj->unlinkAllowed = 0; /* ... or unlink it */
2769                 obj->deleted = 0;
2770                 obj->unlinked = 0;
2771                 obj->yst_mode = mode;
2772                 obj->myDev = dev;
2773 -               obj->chunkId = 0;       /* Not a valid chunk. */
2774 +               obj->hdrChunk = 0;      /* Not a valid chunk. */
2775         }
2776  
2777         return obj;
2778 @@ -1934,14 +1985,14 @@ static yaffs_Object *yaffs_CreateFakeDir
2779  static void yaffs_UnhashObject(yaffs_Object * tn)
2780  {
2781         int bucket;
2782 -       yaffs_Device *dev = tn->myDev;
2783 +        yaffs_Device *dev = tn->myDev;
2784  
2785 -       /* If it is still linked into the bucket list, free from the list */
2786 -       if (!list_empty(&tn->hashLink)) {
2787 -               list_del_init(&tn->hashLink);
2788 -               bucket = yaffs_HashFunction(tn->objectId);
2789 -               dev->objectBucket[bucket].count--;
2790 -       }
2791 +        /* If it is still linked into the bucket list, free from the list */
2792 +        if (!ylist_empty(&tn->hashLink)) {
2793 +                ylist_del_init(&tn->hashLink);
2794 +                bucket = yaffs_HashFunction(tn->objectId);
2795 +                dev->objectBucket[bucket].count--;
2796 +        }
2797  
2798  }
2799  
2800 @@ -1951,6 +2002,13 @@ static void yaffs_FreeObject(yaffs_Objec
2801  
2802         yaffs_Device *dev = tn->myDev;
2803  
2804 +       
2805 +       if(tn->parent)
2806 +               YBUG();
2807 +       if(!ylist_empty(&tn->siblings))
2808 +               YBUG();
2809 +
2810 +
2811  #ifdef  __KERNEL__
2812         if (tn->myInode) {
2813                 /* We're still hooked up to a cached inode.
2814 @@ -1961,12 +2019,18 @@ static void yaffs_FreeObject(yaffs_Objec
2815         }
2816  #endif
2817  
2818 -       yaffs_UnhashObject(tn);
2819 +        yaffs_UnhashObject(tn);
2820 +
2821 +#ifdef VALGRIND_TEST
2822 +       YFREE(tn);
2823 +#else
2824 +        /* Link into the free list. */
2825 +        tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
2826 +        dev->freeObjects = tn;
2827 +        dev->nFreeObjects++;
2828 +#endif
2829 +       dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2830  
2831 -       /* Link into the free list. */
2832 -       tn->siblings.next = (struct list_head *)(dev->freeObjects);
2833 -       dev->freeObjects = tn;
2834 -       dev->nFreeObjects++;
2835  }
2836  
2837  #ifdef __KERNEL__
2838 @@ -2004,12 +2068,12 @@ static void yaffs_InitialiseObjects(yaff
2839  
2840         dev->allocatedObjectList = NULL;
2841         dev->freeObjects = NULL;
2842 -       dev->nFreeObjects = 0;
2843 +        dev->nFreeObjects = 0;
2844  
2845 -       for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2846 -               INIT_LIST_HEAD(&dev->objectBucket[i].list);
2847 -               dev->objectBucket[i].count = 0;
2848 -       }
2849 +        for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2850 +                YINIT_LIST_HEAD(&dev->objectBucket[i].list);
2851 +                dev->objectBucket[i].count = 0;
2852 +        }
2853  
2854  }
2855  
2856 @@ -2055,26 +2119,26 @@ static int yaffs_CreateNewObjectNumber(y
2857  
2858         /* Now find an object value that has not already been taken
2859          * by scanning the list.
2860 -        */
2861 +         */
2862  
2863 -       int found = 0;
2864 -       struct list_head *i;
2865 +        int found = 0;
2866 +        struct ylist_head *i;
2867  
2868 -       __u32 n = (__u32) bucket;
2869 +        __u32 n = (__u32) bucket;
2870  
2871         /* yaffs_CheckObjectHashSanity();  */
2872  
2873         while (!found) {
2874 -               found = 1;
2875 -               n += YAFFS_NOBJECT_BUCKETS;
2876 -               if (1 || dev->objectBucket[bucket].count > 0) {
2877 -                       list_for_each(i, &dev->objectBucket[bucket].list) {
2878 -                               /* If there is already one in the list */
2879 -                               if (i
2880 -                                   && list_entry(i, yaffs_Object,
2881 -                                                 hashLink)->objectId == n) {
2882 -                                       found = 0;
2883 -                               }
2884 +                found = 1;
2885 +                n += YAFFS_NOBJECT_BUCKETS;
2886 +                if (1 || dev->objectBucket[bucket].count > 0) {
2887 +                        ylist_for_each(i, &dev->objectBucket[bucket].list) {
2888 +                                /* If there is already one in the list */
2889 +                                if (i
2890 +                                    && ylist_entry(i, yaffs_Object,
2891 +                                                  hashLink)->objectId == n) {
2892 +                                        found = 0;
2893 +                                }
2894                         }
2895                 }
2896         }
2897 @@ -2085,27 +2149,27 @@ static int yaffs_CreateNewObjectNumber(y
2898  
2899  static void yaffs_HashObject(yaffs_Object * in)
2900  {
2901 -       int bucket = yaffs_HashFunction(in->objectId);
2902 -       yaffs_Device *dev = in->myDev;
2903 +        int bucket = yaffs_HashFunction(in->objectId);
2904 +        yaffs_Device *dev = in->myDev;
2905  
2906 -       list_add(&in->hashLink, &dev->objectBucket[bucket].list);
2907 -       dev->objectBucket[bucket].count++;
2908 +        ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
2909 +        dev->objectBucket[bucket].count++;
2910  
2911  }
2912  
2913  yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
2914  {
2915 -       int bucket = yaffs_HashFunction(number);
2916 -       struct list_head *i;
2917 -       yaffs_Object *in;
2918 -
2919 -       list_for_each(i, &dev->objectBucket[bucket].list) {
2920 -               /* Look if it is in the list */
2921 -               if (i) {
2922 -                       in = list_entry(i, yaffs_Object, hashLink);
2923 -                       if (in->objectId == number) {
2924 +        int bucket = yaffs_HashFunction(number);
2925 +        struct ylist_head *i;
2926 +        yaffs_Object *in;
2927 +
2928 +        ylist_for_each(i, &dev->objectBucket[bucket].list) {
2929 +                /* Look if it is in the list */
2930 +                if (i) {
2931 +                        in = ylist_entry(i, yaffs_Object, hashLink);
2932 +                        if (in->objectId == number) {
2933  #ifdef __KERNEL__
2934 -                               /* Don't tell the VFS about this one if it is defered free */
2935 +                                /* Don't tell the VFS about this one if it is defered free */
2936                                 if (in->deferedFree)
2937                                         return NULL;
2938  #endif
2939 @@ -2123,7 +2187,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2940  {
2941  
2942         yaffs_Object *theObject;
2943 -       yaffs_Tnode *tn;
2944 +       yaffs_Tnode *tn = NULL;
2945  
2946         if (number < 0) {
2947                 number = yaffs_CreateNewObjectNumber(dev);
2948 @@ -2132,7 +2196,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2949         theObject = yaffs_AllocateEmptyObject(dev);
2950         if(!theObject)
2951                 return NULL;
2952 -
2953 +               
2954         if(type == YAFFS_OBJECT_TYPE_FILE){
2955                 tn = yaffs_GetTnode(dev);
2956                 if(!tn){
2957 @@ -2140,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2958                         return NULL;
2959                 }
2960         }
2961 -
2962 -
2963 +               
2964 +       
2965  
2966         if (theObject) {
2967                 theObject->fake = 0;
2968 @@ -2162,19 +2226,25 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2969                 theObject->yst_atime = theObject->yst_mtime =
2970                     theObject->yst_ctime = Y_CURRENT_TIME;
2971  #endif
2972 +
2973 +#if 0
2974 +               theObject->sum_prev = 12345;
2975 +               theObject->sum_trailer = 6789;
2976 +#endif
2977 +
2978                 switch (type) {
2979                 case YAFFS_OBJECT_TYPE_FILE:
2980                         theObject->variant.fileVariant.fileSize = 0;
2981                         theObject->variant.fileVariant.scannedFileSize = 0;
2982                         theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */
2983                         theObject->variant.fileVariant.topLevel = 0;
2984 -                       theObject->variant.fileVariant.top = tn;
2985 -                       break;
2986 -               case YAFFS_OBJECT_TYPE_DIRECTORY:
2987 -                       INIT_LIST_HEAD(&theObject->variant.directoryVariant.
2988 -                                      children);
2989 -                       break;
2990 -               case YAFFS_OBJECT_TYPE_SYMLINK:
2991 +                        theObject->variant.fileVariant.top = tn;
2992 +                        break;
2993 +                case YAFFS_OBJECT_TYPE_DIRECTORY:
2994 +                        YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
2995 +                                       children);
2996 +                        break;
2997 +                case YAFFS_OBJECT_TYPE_SYMLINK:
2998                 case YAFFS_OBJECT_TYPE_HARDLINK:
2999                 case YAFFS_OBJECT_TYPE_SPECIAL:
3000                         /* No action required */
3001 @@ -2205,7 +2275,7 @@ static yaffs_Object *yaffs_FindOrCreateO
3002         return theObject;
3003  
3004  }
3005 -
3006 +                       
3007  
3008  static YCHAR *yaffs_CloneString(const YCHAR * str)
3009  {
3010 @@ -2227,7 +2297,7 @@ static YCHAR *yaffs_CloneString(const YC
3011   * aliasString only has meaning for a sumlink.
3012   * rdev only has meaning for devices (a subset of special objects)
3013   */
3014 -
3015
3016  static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
3017                                        yaffs_Object * parent,
3018                                        const YCHAR * name,
3019 @@ -2238,7 +2308,7 @@ static yaffs_Object *yaffs_MknodObject(y
3020                                        const YCHAR * aliasString, __u32 rdev)
3021  {
3022         yaffs_Object *in;
3023 -       YCHAR *str;
3024 +       YCHAR *str = NULL;
3025  
3026         yaffs_Device *dev = parent->myDev;
3027  
3028 @@ -2249,6 +2319,9 @@ static yaffs_Object *yaffs_MknodObject(y
3029  
3030         in = yaffs_CreateNewObject(dev, -1, type);
3031  
3032 +       if(!in)
3033 +               return YAFFS_FAIL;
3034 +       
3035         if(type == YAFFS_OBJECT_TYPE_SYMLINK){
3036                 str = yaffs_CloneString(aliasString);
3037                 if(!str){
3038 @@ -2256,11 +2329,11 @@ static yaffs_Object *yaffs_MknodObject(y
3039                         return NULL;
3040                 }
3041         }
3042 -
3043 -
3044 +       
3045 +       
3046  
3047         if (in) {
3048 -               in->chunkId = -1;
3049 +               in->hdrChunk = 0;
3050                 in->valid = 1;
3051                 in->variantType = type;
3052  
3053 @@ -2293,13 +2366,13 @@ static yaffs_Object *yaffs_MknodObject(y
3054                         break;
3055                 case YAFFS_OBJECT_TYPE_HARDLINK:
3056                         in->variant.hardLinkVariant.equivalentObject =
3057 -                           equivalentObject;
3058 -                       in->variant.hardLinkVariant.equivalentObjectId =
3059 -                           equivalentObject->objectId;
3060 -                       list_add(&in->hardLinks, &equivalentObject->hardLinks);
3061 -                       break;
3062 -               case YAFFS_OBJECT_TYPE_FILE:
3063 -               case YAFFS_OBJECT_TYPE_DIRECTORY:
3064 +                            equivalentObject;
3065 +                        in->variant.hardLinkVariant.equivalentObjectId =
3066 +                            equivalentObject->objectId;
3067 +                        ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
3068 +                        break;
3069 +                case YAFFS_OBJECT_TYPE_FILE:    
3070 +                case YAFFS_OBJECT_TYPE_DIRECTORY:
3071                 case YAFFS_OBJECT_TYPE_SPECIAL:
3072                 case YAFFS_OBJECT_TYPE_UNKNOWN:
3073                         /* do nothing */
3074 @@ -2378,11 +2451,11 @@ static int yaffs_ChangeObjectName(yaffs_
3075         if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
3076                 T(YAFFS_TRACE_ALWAYS,
3077                   (TSTR
3078 -                  ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
3079 +                  ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"
3080                     TENDSTR)));
3081                 YBUG();
3082         }
3083 -
3084 +       
3085         /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
3086         if (obj->myDev->isYaffs2) {
3087                 unlinkOp = (newDir == obj->myDev->unlinkedDir);
3088 @@ -2395,9 +2468,9 @@ static int yaffs_ChangeObjectName(yaffs_
3089  
3090         existingTarget = yaffs_FindObjectByName(newDir, newName);
3091  
3092 -       /* If the object is a file going into the unlinked directory,
3093 +       /* If the object is a file going into the unlinked directory, 
3094          *   then it is OK to just stuff it in since duplicate names are allowed.
3095 -        *   else only proceed if the new name does not exist and if we're putting
3096 +        *   else only proceed if the new name does not exist and if we're putting 
3097          *   it into a directory.
3098          */
3099         if ((unlinkOp ||
3100 @@ -2425,9 +2498,15 @@ static int yaffs_ChangeObjectName(yaffs_
3101  int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
3102                        yaffs_Object * newDir, const YCHAR * newName)
3103  {
3104 -       yaffs_Object *obj;
3105 -       yaffs_Object *existingTarget;
3106 +       yaffs_Object *obj=NULL;
3107 +       yaffs_Object *existingTarget=NULL;
3108         int force = 0;
3109 +       
3110 +       
3111 +       if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3112 +               YBUG();
3113 +       if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3114 +               YBUG();
3115  
3116  #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
3117         /* Special case for case insemsitive systems (eg. WinCE).
3118 @@ -2439,29 +2518,24 @@ int yaffs_RenameObject(yaffs_Object * ol
3119         }
3120  #endif
3121  
3122 -       obj = yaffs_FindObjectByName(oldDir, oldName);
3123 -       /* Check new name to long. */
3124 -       if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
3125 -           yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
3126 -         /* ENAMETOOLONG */
3127 -         return YAFFS_FAIL;
3128 -       else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
3129 -                yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
3130 +       else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
3131           /* ENAMETOOLONG */
3132           return YAFFS_FAIL;
3133  
3134 +       obj = yaffs_FindObjectByName(oldDir, oldName);
3135 +
3136         if (obj && obj->renameAllowed) {
3137  
3138                 /* Now do the handling for an existing target, if there is one */
3139  
3140 -               existingTarget = yaffs_FindObjectByName(newDir, newName);
3141 -               if (existingTarget &&
3142 -                   existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
3143 -                   !list_empty(&existingTarget->variant.directoryVariant.children)) {
3144 -                       /* There is a target that is a non-empty directory, so we fail */
3145 -                       return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
3146 -               } else if (existingTarget && existingTarget != obj) {
3147 -                       /* Nuke the target first, using shadowing,
3148 +                existingTarget = yaffs_FindObjectByName(newDir, newName);
3149 +                if (existingTarget &&
3150 +                    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
3151 +                    !ylist_empty(&existingTarget->variant.directoryVariant.children)) {
3152 +                        /* There is a target that is a non-empty directory, so we fail */
3153 +                        return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
3154 +                } else if (existingTarget && existingTarget != obj) {
3155 +                       /* Nuke the target first, using shadowing, 
3156                          * but only if it isn't the same object
3157                          */
3158                         yaffs_ChangeObjectName(obj, newDir, newName, force,
3159 @@ -2479,10 +2553,10 @@ int yaffs_RenameObject(yaffs_Object * ol
3160  static int yaffs_InitialiseBlocks(yaffs_Device * dev)
3161  {
3162         int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
3163 -
3164 +       
3165         dev->blockInfo = NULL;
3166         dev->chunkBits = NULL;
3167 -
3168 +       
3169         dev->allocationBlock = -1;      /* force it to get a new one */
3170  
3171         /* If the first allocation strategy fails, thry the alternate one */
3172 @@ -2493,9 +2567,9 @@ static int yaffs_InitialiseBlocks(yaffs_
3173         }
3174         else
3175                 dev->blockInfoAlt = 0;
3176 -
3177 +               
3178         if(dev->blockInfo){
3179 -
3180 +       
3181                 /* Set up dynamic blockinfo stuff. */
3182                 dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
3183                 dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
3184 @@ -2506,7 +2580,7 @@ static int yaffs_InitialiseBlocks(yaffs_
3185                 else
3186                         dev->chunkBitsAlt = 0;
3187         }
3188 -
3189 +       
3190         if (dev->blockInfo && dev->chunkBits) {
3191                 memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
3192                 memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
3193 @@ -2527,7 +2601,7 @@ static void yaffs_DeinitialiseBlocks(yaf
3194         dev->blockInfoAlt = 0;
3195  
3196         dev->blockInfo = NULL;
3197 -
3198 +       
3199         if(dev->chunkBitsAlt && dev->chunkBits)
3200                 YFREE_ALT(dev->chunkBits);
3201         else if(dev->chunkBits)
3202 @@ -2591,14 +2665,14 @@ static int yaffs_FindBlockForGarbageColl
3203         int prioritised=0;
3204         yaffs_BlockInfo *bi;
3205         int pendingPrioritisedExist = 0;
3206 -
3207 +       
3208         /* First let's see if we need to grab a prioritised block */
3209         if(dev->hasPendingPrioritisedGCs){
3210                 for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
3211  
3212                         bi = yaffs_GetBlockInfo(dev, i);
3213                         //yaffs_VerifyBlock(dev,bi,i);
3214 -
3215 +                       
3216                         if(bi->gcPrioritise) {
3217                                 pendingPrioritisedExist = 1;
3218                                 if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3219 @@ -2610,7 +2684,7 @@ static int yaffs_FindBlockForGarbageColl
3220                                 }
3221                         }
3222                 }
3223 -
3224 +               
3225                 if(!pendingPrioritisedExist) /* None found, so we can clear this */
3226                         dev->hasPendingPrioritisedGCs = 0;
3227         }
3228 @@ -2662,7 +2736,7 @@ static int yaffs_FindBlockForGarbageColl
3229                         dirtiest = b;
3230                         pagesInUse = 0;
3231                 }
3232 -               else
3233 +               else 
3234  #endif
3235  
3236                 if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3237 @@ -2699,11 +2773,11 @@ static void yaffs_BlockBecameDirty(yaffs
3238         /* If the block is still healthy erase it and mark as clean.
3239          * If the block has had a data failure, then retire it.
3240          */
3241 -
3242 +        
3243         T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
3244                 (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
3245                 blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
3246 -
3247 +               
3248         bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
3249  
3250         if (!bi->needsRetiring) {
3251 @@ -2716,7 +2790,7 @@ static void yaffs_BlockBecameDirty(yaffs
3252                 }
3253         }
3254  
3255 -       if (erasedOk &&
3256 +       if (erasedOk && 
3257             ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) {
3258                 int i;
3259                 for (i = 0; i < dev->nChunksPerBlock; i++) {
3260 @@ -2763,11 +2837,11 @@ static int yaffs_FindBlockForAllocation(
3261                  * Can't get space to gc
3262                  */
3263                 T(YAFFS_TRACE_ERROR,
3264 -                 (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
3265 +                 (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));
3266  
3267                 return -1;
3268         }
3269 -
3270 +       
3271         /* Find an empty block. */
3272  
3273         for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
3274 @@ -2794,13 +2868,48 @@ static int yaffs_FindBlockForAllocation(
3275  
3276         T(YAFFS_TRACE_ALWAYS,
3277           (TSTR
3278 -          ("yaffs tragedy: no more eraased blocks, but there should have been %d"
3279 +          ("yaffs tragedy: no more erased blocks, but there should have been %d"
3280             TENDSTR), dev->nErasedBlocks));
3281  
3282         return -1;
3283  }
3284  
3285  
3286 +
3287 +static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
3288 +{
3289 +       if(!dev->nCheckpointBlocksRequired &&
3290 +          dev->isYaffs2){
3291 +               /* Not a valid value so recalculate */
3292 +               int nBytes = 0;
3293 +               int nBlocks;
3294 +               int devBlocks = (dev->endBlock - dev->startBlock + 1);
3295 +               int tnodeSize;
3296 +
3297 +               tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
3298 +
3299 +               if(tnodeSize < sizeof(yaffs_Tnode))
3300 +                       tnodeSize = sizeof(yaffs_Tnode);
3301 +               
3302 +               nBytes += sizeof(yaffs_CheckpointValidity);
3303 +               nBytes += sizeof(yaffs_CheckpointDevice);
3304 +               nBytes += devBlocks * sizeof(yaffs_BlockInfo);
3305 +               nBytes += devBlocks * dev->chunkBitmapStride;
3306 +               nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects);
3307 +               nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes);
3308 +               nBytes += sizeof(yaffs_CheckpointValidity);
3309 +               nBytes += sizeof(__u32); /* checksum*/
3310 +       
3311 +               /* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
3312 +       
3313 +               nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3;
3314 +       
3315 +               dev->nCheckpointBlocksRequired = nBlocks;
3316 +       }
3317 +
3318 +       return dev->nCheckpointBlocksRequired;
3319 +}
3320 +
3321  // Check if there's space to allocate...
3322  // Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
3323  static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
3324 @@ -2808,13 +2917,18 @@ static int yaffs_CheckSpaceForAllocation
3325         int reservedChunks;
3326         int reservedBlocks = dev->nReservedBlocks;
3327         int checkpointBlocks;
3328 -
3329 -       checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
3330 -       if(checkpointBlocks < 0)
3331 -               checkpointBlocks = 0;
3332 -
3333 +       
3334 +       if(dev->isYaffs2){
3335 +               checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - 
3336 +                                   dev->blocksInCheckpoint;
3337 +               if(checkpointBlocks < 0)
3338 +                       checkpointBlocks = 0;
3339 +       } else {
3340 +               checkpointBlocks =0;
3341 +       }
3342 +       
3343         reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
3344 -
3345 +       
3346         return (dev->nFreeChunks > reservedChunks);
3347  }
3348  
3349 @@ -2861,10 +2975,10 @@ static int yaffs_AllocateChunk(yaffs_Dev
3350  
3351                 if(blockUsedPtr)
3352                         *blockUsedPtr = bi;
3353 -
3354 +                       
3355                 return retVal;
3356         }
3357 -
3358 +       
3359         T(YAFFS_TRACE_ERROR,
3360           (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
3361  
3362 @@ -2885,17 +2999,17 @@ static int yaffs_GetErasedChunks(yaffs_D
3363  
3364  }
3365  
3366 -static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
3367 +static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlock)
3368  {
3369         int oldChunk;
3370         int newChunk;
3371 -       int chunkInBlock;
3372         int markNAND;
3373         int retVal = YAFFS_OK;
3374         int cleanups = 0;
3375         int i;
3376         int isCheckpointBlock;
3377         int matchingChunk;
3378 +       int maxCopies;
3379  
3380         int chunksBefore = yaffs_GetErasedChunks(dev);
3381         int chunksAfter;
3382 @@ -2907,12 +3021,15 @@ static int yaffs_GarbageCollectBlock(yaf
3383         yaffs_Object *object;
3384  
3385         isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
3386 -
3387 +       
3388         bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
3389  
3390         T(YAFFS_TRACE_TRACING,
3391 -         (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
3392 -          bi->pagesInUse, bi->hasShrinkHeader));
3393 +         (TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR), 
3394 +         block,
3395 +         bi->pagesInUse,
3396 +         bi->hasShrinkHeader,
3397 +         wholeBlock));
3398  
3399         /*yaffs_VerifyFreeChunks(dev); */
3400  
3401 @@ -2935,16 +3052,23 @@ static int yaffs_GarbageCollectBlock(yaf
3402         } else {
3403  
3404                 __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
3405 -
3406 +               
3407                 yaffs_VerifyBlock(dev,bi,block);
3408  
3409 -               for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
3410 -                    chunkInBlock < dev->nChunksPerBlock
3411 -                    && yaffs_StillSomeChunkBits(dev, block);
3412 -                    chunkInBlock++, oldChunk++) {
3413 -                       if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
3414 +               maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10;
3415 +               oldChunk = block * dev->nChunksPerBlock + dev->gcChunk;
3416 +               
3417 +               for ( /* init already done */;
3418 +                    retVal == YAFFS_OK &&
3419 +                    dev->gcChunk < dev->nChunksPerBlock &&
3420 +                    (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING)&&
3421 +                    maxCopies > 0;
3422 +                    dev->gcChunk++, oldChunk++) {
3423 +                       if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) {
3424  
3425                                 /* This page is in use and might need to be copied off */
3426 +                               
3427 +                               maxCopies--;
3428  
3429                                 markNAND = 1;
3430  
3431 @@ -2959,23 +3083,23 @@ static int yaffs_GarbageCollectBlock(yaf
3432  
3433                                 T(YAFFS_TRACE_GC_DETAIL,
3434                                   (TSTR
3435 -                                  ("Collecting page %d, %d %d %d " TENDSTR),
3436 -                                  chunkInBlock, tags.objectId, tags.chunkId,
3437 +                                  ("Collecting chunk in block %d, %d %d %d " TENDSTR),
3438 +                                  dev->gcChunk, tags.objectId, tags.chunkId,
3439                                    tags.byteCount));
3440 -
3441 +                                  
3442                                 if(object && !yaffs_SkipVerification(dev)){
3443                                         if(tags.chunkId == 0)
3444 -                                               matchingChunk = object->chunkId;
3445 +                                               matchingChunk = object->hdrChunk;
3446                                         else if(object->softDeleted)
3447                                                 matchingChunk = oldChunk; /* Defeat the test */
3448                                         else
3449                                                 matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL);
3450 -
3451 +                                       
3452                                         if(oldChunk != matchingChunk)
3453                                                 T(YAFFS_TRACE_ERROR,
3454                                                   (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR),
3455                                                   oldChunk,matchingChunk,tags.objectId, tags.chunkId));
3456 -
3457 +                                               
3458                                 }
3459  
3460                                 if (!object) {
3461 @@ -2986,11 +3110,13 @@ static int yaffs_GarbageCollectBlock(yaf
3462                                             tags.objectId, tags.chunkId, tags.byteCount));
3463                                 }
3464  
3465 -                               if (object && object->deleted
3466 -                                   && tags.chunkId != 0) {
3467 -                                       /* Data chunk in a deleted file, throw it away
3468 +                               if (object && 
3469 +                                   object->deleted &&
3470 +                                   object->softDeleted &&
3471 +                                   tags.chunkId != 0) {
3472 +                                       /* Data chunk in a soft deleted file, throw it away
3473                                          * It's a soft deleted data chunk,
3474 -                                        * No need to copy this, just forget about it and
3475 +                                        * No need to copy this, just forget about it and 
3476                                          * fix up the object.
3477                                          */
3478  
3479 @@ -3009,7 +3135,7 @@ static int yaffs_GarbageCollectBlock(yaf
3480                                         /* Deleted object header with no data chunks.
3481                                          * Can be discarded and the file deleted.
3482                                          */
3483 -                                       object->chunkId = 0;
3484 +                                       object->hdrChunk = 0;
3485                                         yaffs_FreeTnode(object->myDev,
3486                                                         object->variant.
3487                                                         fileVariant.top);
3488 @@ -3037,10 +3163,9 @@ static int yaffs_GarbageCollectBlock(yaf
3489                                                 yaffs_ObjectHeader *oh;
3490                                                 oh = (yaffs_ObjectHeader *)buffer;
3491                                                 oh->isShrink = 0;
3492 -                                               oh->shadowsObject = -1;
3493                                                 tags.extraShadows = 0;
3494                                                 tags.extraIsShrinkHeader = 0;
3495 -
3496 +                                               
3497                                                 yaffs_VerifyObjectHeader(object,oh,&tags,1);
3498                                         }
3499  
3500 @@ -3055,7 +3180,7 @@ static int yaffs_GarbageCollectBlock(yaf
3501  
3502                                                 if (tags.chunkId == 0) {
3503                                                         /* It's a header */
3504 -                                                       object->chunkId =  newChunk;
3505 +                                                       object->hdrChunk =  newChunk;
3506                                                         object->serial =   tags.serialNumber;
3507                                                 } else {
3508                                                         /* It's a data chunk */
3509 @@ -3067,12 +3192,14 @@ static int yaffs_GarbageCollectBlock(yaf
3510                                         }
3511                                 }
3512  
3513 -                               yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
3514 +                               if(retVal == YAFFS_OK)
3515 +                                       yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
3516  
3517                         }
3518                 }
3519  
3520                 yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
3521 +               
3522  
3523  
3524                 /* Do any required cleanups */
3525 @@ -3099,7 +3226,7 @@ static int yaffs_GarbageCollectBlock(yaf
3526         }
3527  
3528         yaffs_VerifyCollectedBlock(dev,bi,block);
3529 -
3530 +         
3531         if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
3532                 T(YAFFS_TRACE_GC,
3533                   (TSTR
3534 @@ -3107,9 +3234,15 @@ static int yaffs_GarbageCollectBlock(yaf
3535                     TENDSTR), chunksBefore, chunksAfter));
3536         }
3537  
3538 +       /* If the gc completed then clear the current gcBlock so that we find another. */
3539 +       if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING){
3540 +               dev->gcBlock = -1;
3541 +               dev->gcChunk = 0;
3542 +       }
3543 +       
3544         dev->isDoingGC = 0;
3545  
3546 -       return YAFFS_OK;
3547 +       return retVal;
3548  }
3549  
3550  /* New garbage collector
3551 @@ -3127,22 +3260,22 @@ static int yaffs_CheckGarbageCollection(
3552         int aggressive;
3553         int gcOk = YAFFS_OK;
3554         int maxTries = 0;
3555 -
3556 +       
3557         int checkpointBlockAdjust;
3558  
3559         if (dev->isDoingGC) {
3560                 /* Bail out so we don't get recursive gc */
3561                 return YAFFS_OK;
3562         }
3563 -
3564 +       
3565         /* This loop should pass the first time.
3566          * We'll only see looping here if the erase of the collected block fails.
3567          */
3568  
3569         do {
3570                 maxTries++;
3571 -
3572 -               checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
3573 +               
3574 +               checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
3575                 if(checkpointBlockAdjust < 0)
3576                         checkpointBlockAdjust = 0;
3577  
3578 @@ -3154,7 +3287,12 @@ static int yaffs_CheckGarbageCollection(
3579                         aggressive = 0;
3580                 }
3581  
3582 -               block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
3583 +               if(dev->gcBlock <= 0){
3584 +                       dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive);
3585 +                       dev->gcChunk = 0;
3586 +               }
3587 +               
3588 +               block = dev->gcBlock;
3589  
3590                 if (block > 0) {
3591                         dev->garbageCollections++;
3592 @@ -3167,7 +3305,7 @@ static int yaffs_CheckGarbageCollection(
3593                            ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
3594                            dev->nErasedBlocks, aggressive));
3595  
3596 -                       gcOk = yaffs_GarbageCollectBlock(dev, block);
3597 +                       gcOk = yaffs_GarbageCollectBlock(dev,block,aggressive);
3598                 }
3599  
3600                 if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
3601 @@ -3176,8 +3314,9 @@ static int yaffs_CheckGarbageCollection(
3602                            ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
3603                             TENDSTR), dev->nErasedBlocks, maxTries, block));
3604                 }
3605 -       } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
3606 -                && (maxTries < 2));
3607 +       } while ((dev->nErasedBlocks < dev->nReservedBlocks) && 
3608 +                (block > 0) &&
3609 +                (maxTries < 2));
3610  
3611         return aggressive ? gcOk : YAFFS_OK;
3612  }
3613 @@ -3326,11 +3465,11 @@ static int yaffs_CheckFileSanity(yaffs_O
3614  static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
3615                                   int chunkInNAND, int inScan)
3616  {
3617 -       /* NB inScan is zero unless scanning.
3618 -        * For forward scanning, inScan is > 0;
3619 +       /* NB inScan is zero unless scanning. 
3620 +        * For forward scanning, inScan is > 0; 
3621          * for backward scanning inScan is < 0
3622          */
3623 -
3624 +        
3625         yaffs_Tnode *tn;
3626         yaffs_Device *dev = in->myDev;
3627         int existingChunk;
3628 @@ -3354,7 +3493,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
3629                 return YAFFS_OK;
3630         }
3631  
3632 -       tn = yaffs_AddOrFindLevel0Tnode(dev,
3633 +       tn = yaffs_AddOrFindLevel0Tnode(dev, 
3634                                         &in->variant.fileVariant,
3635                                         chunkInInode,
3636                                         NULL);
3637 @@ -3366,7 +3505,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
3638  
3639         if (inScan != 0) {
3640                 /* If we're scanning then we need to test for duplicates
3641 -                * NB This does not need to be efficient since it should only ever
3642 +                * NB This does not need to be efficient since it should only ever 
3643                  * happen when the power fails during a write, then only one
3644                  * chunk should ever be affected.
3645                  *
3646 @@ -3374,7 +3513,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
3647                  * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
3648                  */
3649  
3650 -               if (existingChunk != 0) {
3651 +               if (existingChunk > 0) {
3652                         /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
3653                          *    thus we have to do a FindChunkInFile to get the real chunk id.
3654                          *
3655 @@ -3407,18 +3546,20 @@ static int yaffs_PutChunkIntoFile(yaffs_
3656  
3657                         }
3658  
3659 -                       /* NB The deleted flags should be false, otherwise the chunks will
3660 +                       /* NB The deleted flags should be false, otherwise the chunks will 
3661                          * not be loaded during a scan
3662                          */
3663  
3664 -                       newSerial = newTags.serialNumber;
3665 -                       existingSerial = existingTags.serialNumber;
3666 +                       if(inScan > 0) {
3667 +                               newSerial = newTags.serialNumber;
3668 +                               existingSerial = existingTags.serialNumber;
3669 +                       }
3670  
3671                         if ((inScan > 0) &&
3672                             (in->myDev->isYaffs2 ||
3673                              existingChunk <= 0 ||
3674                              ((existingSerial + 1) & 3) == newSerial)) {
3675 -                               /* Forward scanning.
3676 +                               /* Forward scanning.                            
3677                                  * Use new
3678                                  * Delete the old one and drop through to update the tnode
3679                                  */
3680 @@ -3459,7 +3600,7 @@ static int yaffs_ReadChunkDataFromObject
3681                   (TSTR("Chunk %d not found zero instead" TENDSTR),
3682                    chunkInNAND));
3683                 /* get sane (zero) data if you read a hole */
3684 -               memset(buffer, 0, in->myDev->nDataBytesPerChunk);
3685 +               memset(buffer, 0, in->myDev->nDataBytesPerChunk);       
3686                 return 0;
3687         }
3688  
3689 @@ -3474,7 +3615,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
3690  
3691         if (chunkId <= 0)
3692                 return;
3693 -
3694 +               
3695  
3696         dev->nDeletions++;
3697         block = chunkId / dev->nChunksPerBlock;
3698 @@ -3560,6 +3701,14 @@ static int yaffs_WriteChunkDataToObject(
3699         newTags.serialNumber =
3700             (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
3701         newTags.byteCount = nBytes;
3702 +       
3703 +       if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){
3704 +         T(YAFFS_TRACE_ERROR,
3705 +         (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
3706 +         while(1){}
3707 +        }
3708 +       
3709 +       
3710  
3711         newChunkId =
3712             yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
3713 @@ -3601,11 +3750,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3714         __u8 *buffer = NULL;
3715         YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
3716  
3717 -       yaffs_ObjectHeader *oh = NULL;
3718 +        yaffs_ObjectHeader *oh = NULL;
3719 +        
3720 +        yaffs_strcpy(oldName,_Y("silly old name"));
3721  
3722 -       yaffs_strcpy(oldName,"silly old name");
3723  
3724 -       if (!in->fake || force) {
3725 +       if (!in->fake || 
3726 +           in == dev->rootDir || /* The rootDir should also be saved */
3727 +           force) {
3728  
3729                 yaffs_CheckGarbageCollection(dev);
3730                 yaffs_CheckObjectDetailsLoaded(in);
3731 @@ -3613,14 +3765,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3732                 buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
3733                 oh = (yaffs_ObjectHeader *) buffer;
3734  
3735 -               prevChunkId = in->chunkId;
3736 +               prevChunkId = in->hdrChunk;
3737  
3738 -               if (prevChunkId >= 0) {
3739 +               if (prevChunkId > 0) {
3740                         result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
3741                                                         buffer, &oldTags);
3742 -
3743 +                       
3744                         yaffs_VerifyObjectHeader(in,oh,&oldTags,0);
3745 -
3746 +                                                                               
3747                         memcpy(oldName, oh->name, sizeof(oh->name));
3748                 }
3749  
3750 @@ -3628,7 +3780,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3751  
3752                 oh->type = in->variantType;
3753                 oh->yst_mode = in->yst_mode;
3754 -               oh->shadowsObject = shadows;
3755 +               oh->shadowsObject = oh->inbandShadowsObject = shadows;
3756  
3757  #ifdef CONFIG_YAFFS_WINCE
3758                 oh->win_atime[0] = in->win_atime[0];
3759 @@ -3717,7 +3869,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3760  
3761                 if (newChunkId >= 0) {
3762  
3763 -                       in->chunkId = newChunkId;
3764 +                       in->hdrChunk = newChunkId;
3765  
3766                         if (prevChunkId >= 0) {
3767                                 yaffs_DeleteChunk(dev, prevChunkId, 1,
3768 @@ -3748,11 +3900,11 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3769  
3770  /*------------------------ Short Operations Cache ----------------------------------------
3771   *   In many situations where there is no high level buffering (eg WinCE) a lot of
3772 - *   reads might be short sequential reads, and a lot of writes may be short
3773 + *   reads might be short sequential reads, and a lot of writes may be short 
3774   *   sequential writes. eg. scanning/writing a jpeg file.
3775 - *   In these cases, a short read/write cache can provide a huge perfomance benefit
3776 + *   In these cases, a short read/write cache can provide a huge perfomance benefit 
3777   *   with dumb-as-a-rock code.
3778 - *   In Linux, the page cache provides read buffering aand the short op cache provides write
3779 + *   In Linux, the page cache provides read buffering aand the short op cache provides write 
3780   *   buffering.
3781   *
3782   *   There are a limited number (~10) of cache chunks per device so that we don't
3783 @@ -3765,14 +3917,14 @@ static int yaffs_ObjectHasCachedWriteDat
3784         int i;
3785         yaffs_ChunkCache *cache;
3786         int nCaches = obj->myDev->nShortOpCaches;
3787 -
3788 +       
3789         for(i = 0; i < nCaches; i++){
3790                 cache = &dev->srCache[i];
3791                 if (cache->object == obj &&
3792                     cache->dirty)
3793                         return 1;
3794         }
3795 -
3796 +       
3797         return 0;
3798  }
3799  
3800 @@ -3838,7 +3990,7 @@ void yaffs_FlushEntireDeviceCache(yaffs_
3801         yaffs_Object *obj;
3802         int nCaches = dev->nShortOpCaches;
3803         int i;
3804 -
3805 +       
3806         /* Find a dirty object in the cache and flush it...
3807          * until there are no further dirty objects.
3808          */
3809 @@ -3848,53 +4000,33 @@ void yaffs_FlushEntireDeviceCache(yaffs_
3810                         if (dev->srCache[i].object &&
3811                             dev->srCache[i].dirty)
3812                                 obj = dev->srCache[i].object;
3813 -
3814 +                           
3815                 }
3816                 if(obj)
3817                         yaffs_FlushFilesChunkCache(obj);
3818 -
3819 +                       
3820         } while(obj);
3821 -
3822 +       
3823  }
3824  
3825  
3826  /* Grab us a cache chunk for use.
3827 - * First look for an empty one.
3828 + * First look for an empty one. 
3829   * Then look for the least recently used non-dirty one.
3830   * Then look for the least recently used dirty one...., flush and look again.
3831   */
3832  static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
3833  {
3834         int i;
3835 -       int usage;
3836 -       int theOne;
3837  
3838         if (dev->nShortOpCaches > 0) {
3839                 for (i = 0; i < dev->nShortOpCaches; i++) {
3840 -                       if (!dev->srCache[i].object)
3841 +                       if (!dev->srCache[i].object) 
3842                                 return &dev->srCache[i];
3843                 }
3844 -
3845 -               return NULL;
3846 -
3847 -               theOne = -1;
3848 -               usage = 0;      /* just to stop the compiler grizzling */
3849 -
3850 -               for (i = 0; i < dev->nShortOpCaches; i++) {
3851 -                       if (!dev->srCache[i].dirty &&
3852 -                           ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
3853 -                            theOne < 0)) {
3854 -                               usage = dev->srCache[i].lastUse;
3855 -                               theOne = i;
3856 -                       }
3857 -               }
3858 -
3859 -
3860 -               return theOne >= 0 ? &dev->srCache[theOne] : NULL;
3861 -       } else {
3862 -               return NULL;
3863         }
3864  
3865 +       return NULL;
3866  }
3867  
3868  static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
3869 @@ -4032,14 +4164,14 @@ static void yaffs_InvalidateWholeChunkCa
3870  static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
3871  {
3872         yaffs_CheckpointValidity cp;
3873 -
3874 +       
3875         memset(&cp,0,sizeof(cp));
3876 -
3877 +       
3878         cp.structType = sizeof(cp);
3879         cp.magic = YAFFS_MAGIC;
3880         cp.version = YAFFS_CHECKPOINT_VERSION;
3881         cp.head = (head) ? 1 : 0;
3882 -
3883 +       
3884         return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
3885                 1 : 0;
3886  }
3887 @@ -4048,9 +4180,9 @@ static int yaffs_ReadCheckpointValidityM
3888  {
3889         yaffs_CheckpointValidity cp;
3890         int ok;
3891 -
3892 +       
3893         ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
3894 -
3895 +       
3896         if(ok)
3897                 ok = (cp.structType == sizeof(cp)) &&
3898                      (cp.magic == YAFFS_MAGIC) &&
3899 @@ -4059,20 +4191,20 @@ static int yaffs_ReadCheckpointValidityM
3900         return ok ? 1 : 0;
3901  }
3902  
3903 -static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
3904 +static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, 
3905                                            yaffs_Device *dev)
3906  {
3907         cp->nErasedBlocks = dev->nErasedBlocks;
3908         cp->allocationBlock = dev->allocationBlock;
3909         cp->allocationPage = dev->allocationPage;
3910         cp->nFreeChunks = dev->nFreeChunks;
3911 -
3912 +       
3913         cp->nDeletedFiles = dev->nDeletedFiles;
3914         cp->nUnlinkedFiles = dev->nUnlinkedFiles;
3915         cp->nBackgroundDeletions = dev->nBackgroundDeletions;
3916         cp->sequenceNumber = dev->sequenceNumber;
3917         cp->oldestDirtySequence = dev->oldestDirtySequence;
3918 -
3919 +       
3920  }
3921  
3922  static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
3923 @@ -4082,7 +4214,7 @@ static void yaffs_CheckpointDeviceToDevi
3924         dev->allocationBlock = cp->allocationBlock;
3925         dev->allocationPage = cp->allocationPage;
3926         dev->nFreeChunks = cp->nFreeChunks;
3927 -
3928 +       
3929         dev->nDeletedFiles = cp->nDeletedFiles;
3930         dev->nUnlinkedFiles = cp->nUnlinkedFiles;
3931         dev->nBackgroundDeletions = cp->nBackgroundDeletions;
3932 @@ -4098,20 +4230,20 @@ static int yaffs_WriteCheckpointDevice(y
3933         __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
3934  
3935         int ok;
3936 -
3937 +               
3938         /* Write device runtime values*/
3939         yaffs_DeviceToCheckpointDevice(&cp,dev);
3940         cp.structType = sizeof(cp);
3941 -
3942 +       
3943         ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
3944 -
3945 +       
3946         /* Write block info */
3947         if(ok) {
3948                 nBytes = nBlocks * sizeof(yaffs_BlockInfo);
3949                 ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
3950         }
3951 -
3952 -       /* Write chunk bits */
3953 +               
3954 +       /* Write chunk bits */          
3955         if(ok) {
3956                 nBytes = nBlocks * dev->chunkBitmapStride;
3957                 ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
3958 @@ -4126,28 +4258,28 @@ static int yaffs_ReadCheckpointDevice(ya
3959         __u32 nBytes;
3960         __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
3961  
3962 -       int ok;
3963 -
3964 +       int ok; 
3965 +       
3966         ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
3967         if(!ok)
3968                 return 0;
3969 -
3970 +               
3971         if(cp.structType != sizeof(cp))
3972                 return 0;
3973 -
3974 -
3975 +               
3976 +       
3977         yaffs_CheckpointDeviceToDevice(dev,&cp);
3978 -
3979 +       
3980         nBytes = nBlocks * sizeof(yaffs_BlockInfo);
3981 -
3982 +       
3983         ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
3984 -
3985 +       
3986         if(!ok)
3987                 return 0;
3988         nBytes = nBlocks * dev->chunkBitmapStride;
3989 -
3990 +       
3991         ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
3992 -
3993 +       
3994         return ok ? 1 : 0;
3995  }
3996  
3997 @@ -4157,7 +4289,7 @@ static void yaffs_ObjectToCheckpointObje
3998  
3999         cp->objectId = obj->objectId;
4000         cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
4001 -       cp->chunkId = obj->chunkId;
4002 +       cp->hdrChunk = obj->hdrChunk;
4003         cp->variantType = obj->variantType;
4004         cp->deleted = obj->deleted;
4005         cp->softDeleted = obj->softDeleted;
4006 @@ -4167,7 +4299,7 @@ static void yaffs_ObjectToCheckpointObje
4007         cp->unlinkAllowed = obj->unlinkAllowed;
4008         cp->serial = obj->serial;
4009         cp->nDataChunks = obj->nDataChunks;
4010 -
4011 +       
4012         if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
4013                 cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
4014         else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
4015 @@ -4178,9 +4310,9 @@ static void yaffs_CheckpointObjectToObje
4016  {
4017  
4018         yaffs_Object *parent;
4019 -
4020 +       
4021         obj->objectId = cp->objectId;
4022 -
4023 +       
4024         if(cp->parentId)
4025                 parent = yaffs_FindOrCreateObjectByNumber(
4026                                         obj->myDev,
4027 @@ -4188,11 +4320,11 @@ static void yaffs_CheckpointObjectToObje
4028                                         YAFFS_OBJECT_TYPE_DIRECTORY);
4029         else
4030                 parent = NULL;
4031 -
4032 +               
4033         if(parent)
4034                 yaffs_AddObjectToDirectory(parent, obj);
4035  
4036 -       obj->chunkId = cp->chunkId;
4037 +       obj->hdrChunk = cp->hdrChunk;
4038         obj->variantType = cp->variantType;
4039         obj->deleted = cp->deleted;
4040         obj->softDeleted = cp->softDeleted;
4041 @@ -4202,13 +4334,13 @@ static void yaffs_CheckpointObjectToObje
4042         obj->unlinkAllowed = cp->unlinkAllowed;
4043         obj->serial = cp->serial;
4044         obj->nDataChunks = cp->nDataChunks;
4045 -
4046 +       
4047         if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
4048                 obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
4049         else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
4050                 obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
4051  
4052 -       if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
4053 +       if(obj->hdrChunk > 0)
4054                 obj->lazyLoaded = 1;
4055  }
4056  
4057 @@ -4220,7 +4352,11 @@ static int yaffs_CheckpointTnodeWorker(y
4058         int i;
4059         yaffs_Device *dev = in->myDev;
4060         int ok = 1;
4061 -       int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4062 +       int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4063 +
4064 +       if(tnodeSize < sizeof(yaffs_Tnode))
4065 +               tnodeSize = sizeof(yaffs_Tnode);
4066 +       
4067  
4068         if (tn) {
4069                 if (level > 0) {
4070 @@ -4235,10 +4371,9 @@ static int yaffs_CheckpointTnodeWorker(y
4071                         }
4072                 } else if (level == 0) {
4073                         __u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
4074 -                       /* printf("write tnode at %d\n",baseOffset); */
4075                         ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
4076                         if(ok)
4077 -                               ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
4078 +                               ok = (yaffs_CheckpointWrite(dev,tn,tnodeSize) == tnodeSize);
4079                 }
4080         }
4081  
4082 @@ -4250,17 +4385,17 @@ static int yaffs_WriteCheckpointTnodes(y
4083  {
4084         __u32 endMarker = ~0;
4085         int ok = 1;
4086 -
4087 +       
4088         if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
4089                 ok = yaffs_CheckpointTnodeWorker(obj,
4090                                             obj->variant.fileVariant.top,
4091                                             obj->variant.fileVariant.topLevel,
4092                                             0);
4093                 if(ok)
4094 -                       ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
4095 +                       ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == 
4096                                 sizeof(endMarker));
4097         }
4098 -
4099 +       
4100         return ok ? 1 : 0;
4101  }
4102  
4103 @@ -4272,70 +4407,72 @@ static int yaffs_ReadCheckpointTnodes(ya
4104         yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
4105         yaffs_Tnode *tn;
4106         int nread = 0;
4107 +       int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4108  
4109 -       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4110 +       if(tnodeSize < sizeof(yaffs_Tnode))
4111 +               tnodeSize = sizeof(yaffs_Tnode);
4112  
4113 +       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4114 +       
4115         while(ok && (~baseChunk)){
4116                 nread++;
4117                 /* Read level 0 tnode */
4118 -
4119 -
4120 -               /* printf("read  tnode at %d\n",baseChunk); */
4121 +               
4122 +               
4123                 tn = yaffs_GetTnodeRaw(dev);
4124                 if(tn)
4125 -                       ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
4126 -                             (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
4127 +                       ok = (yaffs_CheckpointRead(dev,tn,tnodeSize) == tnodeSize);
4128                 else
4129                         ok = 0;
4130 -
4131 +                       
4132                 if(tn && ok){
4133                         ok = yaffs_AddOrFindLevel0Tnode(dev,
4134                                                         fileStructPtr,
4135                                                         baseChunk,
4136                                                         tn) ? 1 : 0;
4137 -
4138 +                                                       
4139                 }
4140 -
4141 +                       
4142                 if(ok)
4143                         ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4144 -
4145 +               
4146         }
4147  
4148         T(YAFFS_TRACE_CHECKPOINT,(
4149                 TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR),
4150                 nread,baseChunk,ok));
4151  
4152 -       return ok ? 1 : 0;
4153 +       return ok ? 1 : 0;      
4154  }
4155 -
4156
4157  
4158  static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
4159  {
4160         yaffs_Object *obj;
4161 -       yaffs_CheckpointObject cp;
4162 -       int i;
4163 -       int ok = 1;
4164 -       struct list_head *lh;
4165 +        yaffs_CheckpointObject cp;
4166 +        int i;
4167 +        int ok = 1;
4168 +        struct ylist_head *lh;
4169  
4170 -
4171 -       /* Iterate through the objects in each hash entry,
4172 +        
4173 +        /* Iterate through the objects in each hash entry,
4174          * dumping them to the checkpointing stream.
4175 -        */
4176 -
4177 -        for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
4178 -               list_for_each(lh, &dev->objectBucket[i].list) {
4179 -                       if (lh) {
4180 -                               obj = list_entry(lh, yaffs_Object, hashLink);
4181 -                               if (!obj->deferedFree) {
4182 -                                       yaffs_ObjectToCheckpointObject(&cp,obj);
4183 -                                       cp.structType = sizeof(cp);
4184 +         */
4185 +         
4186 +         for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
4187 +                ylist_for_each(lh, &dev->objectBucket[i].list) {
4188 +                        if (lh) {
4189 +                                obj = ylist_entry(lh, yaffs_Object, hashLink);
4190 +                                if (!obj->deferedFree) {
4191 +                                        yaffs_ObjectToCheckpointObject(&cp,obj);
4192 +                                        cp.structType = sizeof(cp);
4193  
4194                                         T(YAFFS_TRACE_CHECKPOINT,(
4195                                                 TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
4196 -                                               cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
4197 +                                               cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk,(unsigned) obj));
4198  
4199                                         ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4200 -
4201 +                                       
4202                                         if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
4203                                                 ok = yaffs_WriteCheckpointTnodes(obj);
4204                                         }
4205 @@ -4343,14 +4480,14 @@ static int yaffs_WriteCheckpointObjects(
4206                         }
4207                 }
4208          }
4209 -
4210 +        
4211          /* Dump end of list */
4212         memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
4213         cp.structType = sizeof(cp);
4214 -
4215 +       
4216         if(ok)
4217                 ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4218 -
4219 +               
4220         return ok ? 1 : 0;
4221  }
4222  
4223 @@ -4361,7 +4498,7 @@ static int yaffs_ReadCheckpointObjects(y
4224         int ok = 1;
4225         int done = 0;
4226         yaffs_Object *hardList = NULL;
4227 -
4228 +       
4229         while(ok && !done) {
4230                 ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
4231                 if(cp.structType != sizeof(cp)) {
4232 @@ -4369,9 +4506,9 @@ static int yaffs_ReadCheckpointObjects(y
4233                                 cp.structType,sizeof(cp),ok));
4234                         ok = 0;
4235                 }
4236 -
4237 +                       
4238                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
4239 -                       cp.objectId,cp.parentId,cp.variantType,cp.chunkId));
4240 +                       cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk));
4241  
4242                 if(ok && cp.objectId == ~0)
4243                         done = 1;
4244 @@ -4380,21 +4517,21 @@ static int yaffs_ReadCheckpointObjects(y
4245                         if(obj) {
4246                                 yaffs_CheckpointObjectToObject(obj,&cp);
4247                                 if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
4248 -                                       ok = yaffs_ReadCheckpointTnodes(obj);
4249 -                               } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4250 -                                       obj->hardLinks.next =
4251 -                                                   (struct list_head *)
4252 -                                                   hardList;
4253 -                                       hardList = obj;
4254 -                               }
4255 -
4256 +                                        ok = yaffs_ReadCheckpointTnodes(obj);
4257 +                                } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4258 +                                        obj->hardLinks.next =
4259 +                                                    (struct ylist_head *)
4260 +                                                    hardList;
4261 +                                        hardList = obj;
4262 +                                }
4263 +                          
4264                         }
4265                 }
4266         }
4267 -
4268 +       
4269         if(ok)
4270                 yaffs_HardlinkFixup(dev,hardList);
4271 -
4272 +       
4273         return ok ? 1 : 0;
4274  }
4275  
4276 @@ -4402,14 +4539,14 @@ static int yaffs_WriteCheckpointSum(yaff
4277  {
4278         __u32 checkpointSum;
4279         int ok;
4280 -
4281 +       
4282         yaffs_GetCheckpointSum(dev,&checkpointSum);
4283 -
4284 +       
4285         ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum));
4286 -
4287 +       
4288         if(!ok)
4289                 return 0;
4290 -
4291 +       
4292         return 1;
4293  }
4294  
4295 @@ -4418,17 +4555,17 @@ static int yaffs_ReadCheckpointSum(yaffs
4296         __u32 checkpointSum0;
4297         __u32 checkpointSum1;
4298         int ok;
4299 -
4300 +       
4301         yaffs_GetCheckpointSum(dev,&checkpointSum0);
4302 -
4303 +       
4304         ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1));
4305 -
4306 +       
4307         if(!ok)
4308                 return 0;
4309 -
4310 +               
4311         if(checkpointSum0 != checkpointSum1)
4312                 return 0;
4313 -
4314 +       
4315         return 1;
4316  }
4317  
4318 @@ -4437,15 +4574,15 @@ static int yaffs_WriteCheckpointData(yaf
4319  {
4320  
4321         int ok = 1;
4322 -
4323 +       
4324         if(dev->skipCheckpointWrite || !dev->isYaffs2){
4325                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR)));
4326                 ok = 0;
4327         }
4328 -
4329 +               
4330         if(ok)
4331                 ok = yaffs_CheckpointOpen(dev,1);
4332 -
4333 +       
4334         if(ok){
4335                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
4336                 ok = yaffs_WriteCheckpointValidityMarker(dev,1);
4337 @@ -4462,18 +4599,18 @@ static int yaffs_WriteCheckpointData(yaf
4338                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
4339                 ok = yaffs_WriteCheckpointValidityMarker(dev,0);
4340         }
4341 -
4342 +       
4343         if(ok){
4344                 ok = yaffs_WriteCheckpointSum(dev);
4345         }
4346 -
4347 -
4348 +       
4349 +       
4350         if(!yaffs_CheckpointClose(dev))
4351                  ok = 0;
4352 -
4353 +                
4354         if(ok)
4355                 dev->isCheckpointed = 1;
4356 -        else
4357 +        else 
4358                 dev->isCheckpointed = 0;
4359  
4360         return dev->isCheckpointed;
4361 @@ -4482,17 +4619,17 @@ static int yaffs_WriteCheckpointData(yaf
4362  static int yaffs_ReadCheckpointData(yaffs_Device *dev)
4363  {
4364         int ok = 1;
4365 -
4366 +       
4367         if(dev->skipCheckpointRead || !dev->isYaffs2){
4368                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR)));
4369                 ok = 0;
4370         }
4371 -
4372 +       
4373         if(ok)
4374                 ok = yaffs_CheckpointOpen(dev,0); /* open for read */
4375 -
4376 +       
4377         if(ok){
4378 -               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4379 +               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));   
4380                 ok = yaffs_ReadCheckpointValidityMarker(dev,1);
4381         }
4382         if(ok){
4383 @@ -4500,14 +4637,14 @@ static int yaffs_ReadCheckpointData(yaff
4384                 ok = yaffs_ReadCheckpointDevice(dev);
4385         }
4386         if(ok){
4387 -               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
4388 +               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));    
4389                 ok = yaffs_ReadCheckpointObjects(dev);
4390         }
4391         if(ok){
4392                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4393                 ok = yaffs_ReadCheckpointValidityMarker(dev,0);
4394         }
4395 -
4396 +       
4397         if(ok){
4398                 ok = yaffs_ReadCheckpointSum(dev);
4399                 T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok));
4400 @@ -4518,7 +4655,7 @@ static int yaffs_ReadCheckpointData(yaff
4401  
4402         if(ok)
4403                 dev->isCheckpointed = 1;
4404 -        else
4405 +        else 
4406                 dev->isCheckpointed = 0;
4407  
4408         return ok ? 1 : 0;
4409 @@ -4527,7 +4664,7 @@ static int yaffs_ReadCheckpointData(yaff
4410  
4411  static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
4412  {
4413 -       if(dev->isCheckpointed ||
4414 +       if(dev->isCheckpointed || 
4415            dev->blocksInCheckpoint > 0){
4416                 dev->isCheckpointed = 0;
4417                 yaffs_CheckpointInvalidateStream(dev);
4418 @@ -4550,7 +4687,7 @@ int yaffs_CheckpointSave(yaffs_Device *d
4419                 yaffs_InvalidateCheckpoint(dev);
4420                 yaffs_WriteCheckpointData(dev);
4421         }
4422 -
4423 +       
4424         T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4425  
4426         return dev->isCheckpointed;
4427 @@ -4560,7 +4697,7 @@ int yaffs_CheckpointRestore(yaffs_Device
4428  {
4429         int retval;
4430         T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4431 -
4432 +               
4433         retval = yaffs_ReadCheckpointData(dev);
4434  
4435         if(dev->isCheckpointed){
4436 @@ -4570,7 +4707,7 @@ int yaffs_CheckpointRestore(yaffs_Device
4437         }
4438  
4439         T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4440 -
4441 +       
4442         return retval;
4443  }
4444  
4445 @@ -4589,7 +4726,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4446  {
4447  
4448         int chunk;
4449 -       int start;
4450 +       __u32 start;
4451         int nToCopy;
4452         int n = nBytes;
4453         int nDone = 0;
4454 @@ -4606,7 +4743,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4455                 chunk++;
4456  
4457                 /* OK now check for the curveball where the start and end are in
4458 -                * the same chunk.
4459 +                * the same chunk.      
4460                  */
4461                 if ((start + n) < dev->nDataBytesPerChunk) {
4462                         nToCopy = n;
4463 @@ -4617,10 +4754,10 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4464                 cache = yaffs_FindChunkCache(in, chunk);
4465  
4466                 /* If the chunk is already in the cache or it is less than a whole chunk
4467 -                * then use the cache (if there is caching)
4468 +                * or we're using inband tags then use the cache (if there is caching)
4469                  * else bypass the cache.
4470                  */
4471 -               if (cache || nToCopy != dev->nDataBytesPerChunk) {
4472 +               if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
4473                         if (dev->nShortOpCaches > 0) {
4474  
4475                                 /* If we can't find the data in the cache, then load it up. */
4476 @@ -4641,14 +4778,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4477  
4478                                 cache->locked = 1;
4479  
4480 -#ifdef CONFIG_YAFFS_WINCE
4481 -                               yfsd_UnlockYAFFS(TRUE);
4482 -#endif
4483 +
4484                                 memcpy(buffer, &cache->data[start], nToCopy);
4485  
4486 -#ifdef CONFIG_YAFFS_WINCE
4487 -                               yfsd_LockYAFFS(TRUE);
4488 -#endif
4489                                 cache->locked = 0;
4490                         } else {
4491                                 /* Read into the local buffer then copy..*/
4492 @@ -4657,41 +4789,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
4493                                     yaffs_GetTempBuffer(dev, __LINE__);
4494                                 yaffs_ReadChunkDataFromObject(in, chunk,
4495                                                               localBuffer);
4496 -#ifdef CONFIG_YAFFS_WINCE
4497 -                               yfsd_UnlockYAFFS(TRUE);
4498 -#endif
4499 +
4500                                 memcpy(buffer, &localBuffer[start], nToCopy);
4501  
4502 -#ifdef CONFIG_YAFFS_WINCE
4503 -                               yfsd_LockYAFFS(TRUE);
4504 -#endif
4505 +
4506                                 yaffs_ReleaseTempBuffer(dev, localBuffer,
4507                                                         __LINE__);
4508                         }
4509  
4510                 } else {
4511 -#ifdef CONFIG_YAFFS_WINCE
4512 -                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4513 -
4514 -                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
4515 -                        * This is because we otherwise screw up WinCE's memory mapper
4516 -                        */
4517 -                       yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
4518 -
4519 -#ifdef CONFIG_YAFFS_WINCE
4520 -                       yfsd_UnlockYAFFS(TRUE);
4521 -#endif
4522 -                       memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
4523  
4524 -#ifdef CONFIG_YAFFS_WINCE
4525 -                       yfsd_LockYAFFS(TRUE);
4526 -                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
4527 -#endif
4528 -
4529 -#else
4530                         /* A full chunk. Read directly into the supplied buffer. */
4531                         yaffs_ReadChunkDataFromObject(in, chunk, buffer);
4532 -#endif
4533 +
4534                 }
4535  
4536                 n -= nToCopy;
4537 @@ -4709,14 +4819,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
4538  {
4539  
4540         int chunk;
4541 -       int start;
4542 +       __u32 start;
4543         int nToCopy;
4544 -       int n = nBytes;
4545 -       int nDone = 0;
4546 -       int nToWriteBack;
4547 -       int startOfWrite = offset;
4548 -       int chunkWritten = 0;
4549 -       int nBytesRead;
4550 +        int n = nBytes;
4551 +        int nDone = 0;
4552 +        int nToWriteBack;
4553 +        int startOfWrite = offset;
4554 +        int chunkWritten = 0;
4555 +        __u32 nBytesRead;
4556 +        __u32 chunkStart;
4557  
4558         yaffs_Device *dev;
4559  
4560 @@ -4726,6 +4837,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
4561                 //chunk = offset / dev->nDataBytesPerChunk + 1;
4562                 //start = offset % dev->nDataBytesPerChunk;
4563                 yaffs_AddrToChunk(dev,offset,&chunk,&start);
4564 +               
4565 +               if(chunk * dev->nDataBytesPerChunk + start != offset ||
4566 +                  start >= dev->nDataBytesPerChunk){
4567 +                  T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
4568 +                                       (int)offset, chunk,start));
4569 +               }
4570                 chunk++;
4571  
4572                 /* OK now check for the curveball where the start and end are in
4573 @@ -4740,9 +4857,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
4574                          * we need to write back as much as was there before.
4575                          */
4576  
4577 -                       nBytesRead =
4578 -                           in->variant.fileVariant.fileSize -
4579 -                           ((chunk - 1) * dev->nDataBytesPerChunk);
4580 +                       chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk);
4581 +
4582 +                       if(chunkStart > in->variant.fileVariant.fileSize)
4583 +                               nBytesRead = 0; /* Past end of file */
4584 +                       else
4585 +                               nBytesRead = in->variant.fileVariant.fileSize - chunkStart;
4586  
4587                         if (nBytesRead > dev->nDataBytesPerChunk) {
4588                                 nBytesRead = dev->nDataBytesPerChunk;
4589 @@ -4751,19 +4871,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
4590                         nToWriteBack =
4591                             (nBytesRead >
4592                              (start + n)) ? nBytesRead : (start + n);
4593 +                       
4594 +                       if(nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk)
4595 +                               YBUG();
4596  
4597                 } else {
4598                         nToCopy = dev->nDataBytesPerChunk - start;
4599                         nToWriteBack = dev->nDataBytesPerChunk;
4600                 }
4601  
4602 -               if (nToCopy != dev->nDataBytesPerChunk) {
4603 -                       /* An incomplete start or end chunk (or maybe both start and end chunk) */
4604 +               if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
4605 +                       /* An incomplete start or end chunk (or maybe both start and end chunk), 
4606 +                        * or we're using inband tags, so we want to use the cache buffers.
4607 +                        */
4608                         if (dev->nShortOpCaches > 0) {
4609                                 yaffs_ChunkCache *cache;
4610                                 /* If we can't find the data in the cache, then load the cache */
4611                                 cache = yaffs_FindChunkCache(in, chunk);
4612 -
4613 +                               
4614                                 if (!cache
4615                                     && yaffs_CheckSpaceForAllocation(in->
4616                                                                      myDev)) {
4617 @@ -4776,28 +4901,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
4618                                                                       cache->
4619                                                                       data);
4620                                 }
4621 -                               else if(cache &&
4622 +                               else if(cache && 
4623                                         !cache->dirty &&
4624                                         !yaffs_CheckSpaceForAllocation(in->myDev)){
4625                                         /* Drop the cache if it was a read cache item and
4626                                          * no space check has been made for it.
4627 -                                        */
4628 +                                        */ 
4629                                          cache = NULL;
4630                                 }
4631  
4632                                 if (cache) {
4633                                         yaffs_UseChunkCache(dev, cache, 1);
4634                                         cache->locked = 1;
4635 -#ifdef CONFIG_YAFFS_WINCE
4636 -                                       yfsd_UnlockYAFFS(TRUE);
4637 -#endif
4638 +
4639  
4640                                         memcpy(&cache->data[start], buffer,
4641                                                nToCopy);
4642  
4643 -#ifdef CONFIG_YAFFS_WINCE
4644 -                                       yfsd_LockYAFFS(TRUE);
4645 -#endif
4646 +
4647                                         cache->locked = 0;
4648                                         cache->nBytes = nToWriteBack;
4649  
4650 @@ -4825,15 +4946,10 @@ int yaffs_WriteDataToFile(yaffs_Object *
4651                                 yaffs_ReadChunkDataFromObject(in, chunk,
4652                                                               localBuffer);
4653  
4654 -#ifdef CONFIG_YAFFS_WINCE
4655 -                               yfsd_UnlockYAFFS(TRUE);
4656 -#endif
4657 +
4658  
4659                                 memcpy(&localBuffer[start], buffer, nToCopy);
4660  
4661 -#ifdef CONFIG_YAFFS_WINCE
4662 -                               yfsd_LockYAFFS(TRUE);
4663 -#endif
4664                                 chunkWritten =
4665                                     yaffs_WriteChunkDataToObject(in, chunk,
4666                                                                  localBuffer,
4667 @@ -4846,31 +4962,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
4668                         }
4669  
4670                 } else {
4671 -
4672 -#ifdef CONFIG_YAFFS_WINCE
4673 -                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
4674 -                        * This is because we otherwise screw up WinCE's memory mapper
4675 -                        */
4676 -                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4677 -#ifdef CONFIG_YAFFS_WINCE
4678 -                       yfsd_UnlockYAFFS(TRUE);
4679 -#endif
4680 -                       memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
4681 -#ifdef CONFIG_YAFFS_WINCE
4682 -                       yfsd_LockYAFFS(TRUE);
4683 -#endif
4684 -                       chunkWritten =
4685 -                           yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
4686 -                                                        dev->nDataBytesPerChunk,
4687 -                                                        0);
4688 -                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
4689 -#else
4690                         /* A full chunk. Write directly from the supplied buffer. */
4691 +                       
4692 +
4693 +
4694                         chunkWritten =
4695                             yaffs_WriteChunkDataToObject(in, chunk, buffer,
4696                                                          dev->nDataBytesPerChunk,
4697                                                          0);
4698 -#endif
4699 +
4700                         /* Since we've overwritten the cached data, we better invalidate it. */
4701                         yaffs_InvalidateChunkCache(in, chunk);
4702                 }
4703 @@ -4943,9 +5043,9 @@ int yaffs_ResizeFile(yaffs_Object * in, 
4704  {
4705  
4706         int oldFileSize = in->variant.fileVariant.fileSize;
4707 -       int newSizeOfPartialChunk;
4708 +       __u32 newSizeOfPartialChunk;
4709         int newFullChunks;
4710 -
4711 +       
4712         yaffs_Device *dev = in->myDev;
4713  
4714         yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
4715 @@ -4953,23 +5053,23 @@ int yaffs_ResizeFile(yaffs_Object * in, 
4716         yaffs_FlushFilesChunkCache(in);
4717         yaffs_InvalidateWholeChunkCache(in);
4718  
4719 -       yaffs_CheckGarbageCollection(dev);
4720 +        yaffs_CheckGarbageCollection(dev);
4721  
4722 -       if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
4723 -               return yaffs_GetFileSize(in);
4724 -       }
4725 +        if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
4726 +                return YAFFS_FAIL;
4727 +        }
4728  
4729 -       if (newSize == oldFileSize) {
4730 -               return oldFileSize;
4731 -       }
4732 +        if (newSize == oldFileSize) {
4733 +                return YAFFS_OK;
4734 +        }
4735  
4736 -       if (newSize < oldFileSize) {
4737 +        if (newSize < oldFileSize) {
4738  
4739                 yaffs_PruneResizedChunks(in, newSize);
4740  
4741                 if (newSizeOfPartialChunk != 0) {
4742                         int lastChunk = 1 + newFullChunks;
4743 -
4744 +                       
4745                         __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4746  
4747                         /* Got to read and rewrite the last chunk with its new size and zero pad */
4748 @@ -4993,19 +5093,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
4749                 in->variant.fileVariant.fileSize = newSize;
4750         }
4751  
4752 -
4753 -
4754 +               
4755 +       
4756         /* Write a new object header.
4757          * show we've shrunk the file, if need be
4758          * Do this only if the file is not in the deleted directories.
4759          */
4760 -       if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
4761 +       if (in->parent &&
4762 +           in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
4763             in->parent->objectId != YAFFS_OBJECTID_DELETED) {
4764                 yaffs_UpdateObjectHeader(in, NULL, 0,
4765                                          (newSize < oldFileSize) ? 1 : 0, 0);
4766         }
4767  
4768 -       return newSize;
4769 +       return YAFFS_OK;
4770  }
4771  
4772  loff_t yaffs_GetFileSize(yaffs_Object * obj)
4773 @@ -5058,13 +5159,13 @@ static int yaffs_DoGenericObjectDeletion
4774  
4775         if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
4776                 /* Move to the unlinked directory so we have a record that it was deleted. */
4777 -               yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
4778 +               yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
4779  
4780         }
4781  
4782         yaffs_RemoveObjectFromDirectory(in);
4783 -       yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
4784 -       in->chunkId = -1;
4785 +       yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__);
4786 +       in->hdrChunk = 0;
4787  
4788         yaffs_FreeObject(in);
4789         return YAFFS_OK;
4790 @@ -5075,62 +5176,66 @@ static int yaffs_DoGenericObjectDeletion
4791   * and the inode associated with the file.
4792   * It does not delete the links associated with the file.
4793   */
4794
4795  static int yaffs_UnlinkFile(yaffs_Object * in)
4796  {
4797  
4798         int retVal;
4799         int immediateDeletion = 0;
4800  
4801 -       if (1) {
4802  #ifdef __KERNEL__
4803 -               if (!in->myInode) {
4804 -                       immediateDeletion = 1;
4805 -
4806 -               }
4807 +       if (!in->myInode) {
4808 +               immediateDeletion = 1;
4809 +       }
4810  #else
4811 -               if (in->inUse <= 0) {
4812 -                       immediateDeletion = 1;
4813 -
4814 -               }
4815 +       if (in->inUse <= 0) {
4816 +               immediateDeletion = 1;
4817 +       }
4818  #endif
4819 -               if (immediateDeletion) {
4820 -                       retVal =
4821 -                           yaffs_ChangeObjectName(in, in->myDev->deletedDir,
4822 -                                                  "deleted", 0, 0);
4823 -                       T(YAFFS_TRACE_TRACING,
4824 -                         (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
4825 -                          in->objectId));
4826 -                       in->deleted = 1;
4827 -                       in->myDev->nDeletedFiles++;
4828 -                       if (0 && in->myDev->isYaffs2) {
4829 -                               yaffs_ResizeFile(in, 0);
4830 -                       }
4831 -                       yaffs_SoftDeleteFile(in);
4832 -               } else {
4833 -                       retVal =
4834 -                           yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
4835 -                                                  "unlinked", 0, 0);
4836 -               }
4837  
4838 +       if (immediateDeletion) {
4839 +               retVal =
4840 +                   yaffs_ChangeObjectName(in, in->myDev->deletedDir,
4841 +                                          _Y("deleted"), 0, 0);
4842 +               T(YAFFS_TRACE_TRACING,
4843 +                 (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
4844 +                  in->objectId));
4845 +               in->deleted = 1;
4846 +               in->myDev->nDeletedFiles++;
4847 +               if (1 || in->myDev->isYaffs2) {
4848 +                       yaffs_ResizeFile(in, 0);
4849 +               }
4850 +               yaffs_SoftDeleteFile(in);
4851 +       } else {
4852 +               retVal =
4853 +                   yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
4854 +                                          _Y("unlinked"), 0, 0);
4855         }
4856 +
4857 +
4858         return retVal;
4859  }
4860  
4861  int yaffs_DeleteFile(yaffs_Object * in)
4862  {
4863         int retVal = YAFFS_OK;
4864 +       int deleted = in->deleted;
4865 +       
4866 +       yaffs_ResizeFile(in,0);
4867  
4868         if (in->nDataChunks > 0) {
4869 -               /* Use soft deletion if there is data in the file */
4870 +               /* Use soft deletion if there is data in the file.
4871 +                * That won't be the case if it has been resized to zero.
4872 +                */
4873                 if (!in->unlinked) {
4874                         retVal = yaffs_UnlinkFile(in);
4875                 }
4876                 if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
4877 -                       in->deleted = 1;
4878 +                       in->deleted = deleted = 1;
4879                         in->myDev->nDeletedFiles++;
4880                         yaffs_SoftDeleteFile(in);
4881                 }
4882 -               return in->deleted ? YAFFS_OK : YAFFS_FAIL;
4883 +               return deleted ? YAFFS_OK : YAFFS_FAIL;
4884         } else {
4885                 /* The file has no data chunks so we toss it immediately */
4886                 yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
4887 @@ -5143,10 +5248,10 @@ int yaffs_DeleteFile(yaffs_Object * in)
4888  
4889  static int yaffs_DeleteDirectory(yaffs_Object * in)
4890  {
4891 -       /* First check that the directory is empty. */
4892 -       if (list_empty(&in->variant.directoryVariant.children)) {
4893 -               return yaffs_DoGenericObjectDeletion(in);
4894 -       }
4895 +        /* First check that the directory is empty. */
4896 +        if (ylist_empty(&in->variant.directoryVariant.children)) {
4897 +                return yaffs_DoGenericObjectDeletion(in);
4898 +        }
4899  
4900         return YAFFS_FAIL;
4901  
4902 @@ -5161,11 +5266,11 @@ static int yaffs_DeleteSymLink(yaffs_Obj
4903  
4904  static int yaffs_DeleteHardLink(yaffs_Object * in)
4905  {
4906 -       /* remove this hardlink from the list assocaited with the equivalent
4907 -        * object
4908 -        */
4909 -       list_del(&in->hardLinks);
4910 -       return yaffs_DoGenericObjectDeletion(in);
4911 +        /* remove this hardlink from the list assocaited with the equivalent
4912 +         * object
4913 +         */
4914 +        ylist_del_init(&in->hardLinks);
4915 +        return yaffs_DoGenericObjectDeletion(in);
4916  }
4917  
4918  static void yaffs_DestroyObject(yaffs_Object * obj)
4919 @@ -5194,12 +5299,12 @@ static void yaffs_DestroyObject(yaffs_Ob
4920  static int yaffs_UnlinkWorker(yaffs_Object * obj)
4921  {
4922  
4923 -       if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4924 -               return yaffs_DeleteHardLink(obj);
4925 -       } else if (!list_empty(&obj->hardLinks)) {
4926 -               /* Curve ball: We're unlinking an object that has a hardlink.
4927 -                *
4928 -                * This problem arises because we are not strictly following
4929 +        if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4930 +                return yaffs_DeleteHardLink(obj);
4931 +        } else if (!ylist_empty(&obj->hardLinks)) {
4932 +                /* Curve ball: We're unlinking an object that has a hardlink.
4933 +                 *
4934 +                 * This problem arises because we are not strictly following
4935                  * The Linux link/inode model.
4936                  *
4937                  * We can't really delete the object.
4938 @@ -5212,15 +5317,15 @@ static int yaffs_UnlinkWorker(yaffs_Obje
4939                  */
4940  
4941                 yaffs_Object *hl;
4942 -               int retVal;
4943 -               YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
4944 +                int retVal;
4945 +                YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
4946  
4947 -               hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
4948 +                hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
4949  
4950 -               list_del_init(&hl->hardLinks);
4951 -               list_del_init(&hl->siblings);
4952 +                ylist_del_init(&hl->hardLinks);
4953 +                ylist_del_init(&hl->siblings);
4954  
4955 -               yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
4956 +                yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
4957  
4958                 retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
4959  
4960 @@ -5313,7 +5418,7 @@ static void yaffs_HardlinkFixup(yaffs_De
4961  {
4962         yaffs_Object *hl;
4963         yaffs_Object *in;
4964 -
4965 +       
4966         while (hardList) {
4967                 hl = hardList;
4968                 hardList = (yaffs_Object *) (hardList->hardLinks.next);
4969 @@ -5322,18 +5427,18 @@ static void yaffs_HardlinkFixup(yaffs_De
4970                                               hl->variant.hardLinkVariant.
4971                                               equivalentObjectId);
4972  
4973 -               if (in) {
4974 -                       /* Add the hardlink pointers */
4975 -                       hl->variant.hardLinkVariant.equivalentObject = in;
4976 -                       list_add(&hl->hardLinks, &in->hardLinks);
4977 -               } else {
4978 -                       /* Todo Need to report/handle this better.
4979 -                        * Got a problem... hardlink to a non-existant object
4980 -                        */
4981 -                       hl->variant.hardLinkVariant.equivalentObject = NULL;
4982 -                       INIT_LIST_HEAD(&hl->hardLinks);
4983 +                if (in) {
4984 +                        /* Add the hardlink pointers */
4985 +                        hl->variant.hardLinkVariant.equivalentObject = in;
4986 +                        ylist_add(&hl->hardLinks, &in->hardLinks);
4987 +                } else {
4988 +                        /* Todo Need to report/handle this better.
4989 +                         * Got a problem... hardlink to a non-existant object
4990 +                         */
4991 +                        hl->variant.hardLinkVariant.equivalentObject = NULL;
4992 +                        YINIT_LIST_HEAD(&hl->hardLinks);
4993  
4994 -               }
4995 +                }
4996  
4997         }
4998  
4999 @@ -5355,6 +5460,42 @@ static int ybicmp(const void *a, const v
5000  
5001  }
5002  
5003 +
5004 +struct yaffs_ShadowFixerStruct {
5005 +       int objectId;
5006 +       int shadowedId;
5007 +       struct yaffs_ShadowFixerStruct *next;
5008 +};
5009 +
5010 +
5011 +static void yaffs_StripDeletedObjects(yaffs_Device *dev)
5012 +{
5013 +       /*
5014 +       *  Sort out state of unlinked and deleted objects after scanning.
5015 +       */
5016 +       struct ylist_head *i;
5017 +       struct ylist_head *n;
5018 +       yaffs_Object *l;
5019 +
5020 +       /* Soft delete all the unlinked files */
5021 +       ylist_for_each_safe(i, n,
5022 +               &dev->unlinkedDir->variant.directoryVariant.children) {
5023 +               if (i) {
5024 +                       l = ylist_entry(i, yaffs_Object, siblings);
5025 +                       yaffs_DestroyObject(l);
5026 +               }
5027 +       }
5028 +       
5029 +       ylist_for_each_safe(i, n,
5030 +               &dev->deletedDir->variant.directoryVariant.children) {
5031 +               if (i) {
5032 +                       l = ylist_entry(i, yaffs_Object, siblings);
5033 +                       yaffs_DestroyObject(l);
5034 +               }
5035 +       }
5036 +
5037 +}
5038 +
5039  static int yaffs_Scan(yaffs_Device * dev)
5040  {
5041         yaffs_ExtendedTags tags;
5042 @@ -5362,7 +5503,6 @@ static int yaffs_Scan(yaffs_Device * dev
5043         int blockIterator;
5044         int startIterator;
5045         int endIterator;
5046 -       int nBlocksToScan = 0;
5047         int result;
5048  
5049         int chunk;
5050 @@ -5371,27 +5511,20 @@ static int yaffs_Scan(yaffs_Device * dev
5051         yaffs_BlockState state;
5052         yaffs_Object *hardList = NULL;
5053         yaffs_BlockInfo *bi;
5054 -       int sequenceNumber;
5055 +       __u32 sequenceNumber;
5056         yaffs_ObjectHeader *oh;
5057         yaffs_Object *in;
5058         yaffs_Object *parent;
5059 -       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
5060 -
5061 +       
5062         int alloc_failed = 0;
5063 -
5064 +       
5065 +       struct yaffs_ShadowFixerStruct *shadowFixerList = NULL;
5066 +       
5067  
5068         __u8 *chunkData;
5069  
5070 -       yaffs_BlockIndex *blockIndex = NULL;
5071 -
5072 -       if (dev->isYaffs2) {
5073 -               T(YAFFS_TRACE_SCAN,
5074 -                 (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
5075 -               return YAFFS_FAIL;
5076 -       }
5077 -
5078 -       //TODO  Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
5079 -
5080 +       
5081 +       
5082         T(YAFFS_TRACE_SCAN,
5083           (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
5084            dev->internalStartBlock, dev->internalEndBlock));
5085 @@ -5400,12 +5533,6 @@ static int yaffs_Scan(yaffs_Device * dev
5086  
5087         dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
5088  
5089 -       if (dev->isYaffs2) {
5090 -               blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
5091 -               if(!blockIndex)
5092 -                       return YAFFS_FAIL;
5093 -       }
5094 -
5095         /* Scan all the blocks to determine their state */
5096         for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
5097                 bi = yaffs_GetBlockInfo(dev, blk);
5098 @@ -5430,70 +5557,21 @@ static int yaffs_Scan(yaffs_Device * dev
5099                           (TSTR("Block empty " TENDSTR)));
5100                         dev->nErasedBlocks++;
5101                         dev->nFreeChunks += dev->nChunksPerBlock;
5102 -               } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
5103 -
5104 -                       /* Determine the highest sequence number */
5105 -                       if (dev->isYaffs2 &&
5106 -                           sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5107 -                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
5108 -
5109 -                               blockIndex[nBlocksToScan].seq = sequenceNumber;
5110 -                               blockIndex[nBlocksToScan].block = blk;
5111 -
5112 -                               nBlocksToScan++;
5113 -
5114 -                               if (sequenceNumber >= dev->sequenceNumber) {
5115 -                                       dev->sequenceNumber = sequenceNumber;
5116 -                               }
5117 -                       } else if (dev->isYaffs2) {
5118 -                               /* TODO: Nasty sequence number! */
5119 -                               T(YAFFS_TRACE_SCAN,
5120 -                                 (TSTR
5121 -                                  ("Block scanning block %d has bad sequence number %d"
5122 -                                   TENDSTR), blk, sequenceNumber));
5123 -
5124 -                       }
5125 -               }
5126 +               } 
5127         }
5128  
5129 -       /* Sort the blocks
5130 -        * Dungy old bubble sort for now...
5131 -        */
5132 -       if (dev->isYaffs2) {
5133 -               yaffs_BlockIndex temp;
5134 -               int i;
5135 -               int j;
5136 -
5137 -               for (i = 0; i < nBlocksToScan; i++)
5138 -                       for (j = i + 1; j < nBlocksToScan; j++)
5139 -                               if (blockIndex[i].seq > blockIndex[j].seq) {
5140 -                                       temp = blockIndex[j];
5141 -                                       blockIndex[j] = blockIndex[i];
5142 -                                       blockIndex[i] = temp;
5143 -                               }
5144 -       }
5145 -
5146 -       /* Now scan the blocks looking at the data. */
5147 -       if (dev->isYaffs2) {
5148 -               startIterator = 0;
5149 -               endIterator = nBlocksToScan - 1;
5150 -               T(YAFFS_TRACE_SCAN_DEBUG,
5151 -                 (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
5152 -       } else {
5153 -               startIterator = dev->internalStartBlock;
5154 -               endIterator = dev->internalEndBlock;
5155 -       }
5156 +       startIterator = dev->internalStartBlock;
5157 +       endIterator = dev->internalEndBlock;
5158  
5159         /* For each block.... */
5160         for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
5161              blockIterator++) {
5162 +               
5163 +               YYIELD();
5164  
5165 -               if (dev->isYaffs2) {
5166 -                       /* get the block to scan in the correct order */
5167 -                       blk = blockIndex[blockIterator].block;
5168 -               } else {
5169 -                       blk = blockIterator;
5170 -               }
5171 +               YYIELD();
5172 +               
5173 +               blk = blockIterator;
5174  
5175                 bi = yaffs_GetBlockInfo(dev, blk);
5176                 state = bi->blockState;
5177 @@ -5511,7 +5589,7 @@ static int yaffs_Scan(yaffs_Device * dev
5178  
5179                         /* Let's have a good look at this chunk... */
5180  
5181 -                       if (!dev->isYaffs2 && tags.chunkDeleted) {
5182 +                       if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {
5183                                 /* YAFFS1 only...
5184                                  * A deleted chunk
5185                                  */
5186 @@ -5520,7 +5598,7 @@ static int yaffs_Scan(yaffs_Device * dev
5187                                 /*T((" %d %d deleted\n",blk,c)); */
5188                         } else if (!tags.chunkUsed) {
5189                                 /* An unassigned chunk in the block
5190 -                                * This means that either the block is empty or
5191 +                                * This means that either the block is empty or 
5192                                  * this is the one being allocated from
5193                                  */
5194  
5195 @@ -5537,21 +5615,9 @@ static int yaffs_Scan(yaffs_Device * dev
5196                                         state = YAFFS_BLOCK_STATE_ALLOCATING;
5197                                         dev->allocationBlock = blk;
5198                                         dev->allocationPage = c;
5199 -                                       dev->allocationBlockFinder = blk;
5200 +                                       dev->allocationBlockFinder = blk;       
5201                                         /* Set it to here to encourage the allocator to go forth from here. */
5202 -
5203 -                                       /* Yaffs2 sanity check:
5204 -                                        * This should be the one with the highest sequence number
5205 -                                        */
5206 -                                       if (dev->isYaffs2
5207 -                                           && (dev->sequenceNumber !=
5208 -                                               bi->sequenceNumber)) {
5209 -                                               T(YAFFS_TRACE_ALWAYS,
5210 -                                                 (TSTR
5211 -                                                  ("yaffs: Allocation block %d was not highest sequence id:"
5212 -                                                   " block seq = %d, dev seq = %d"
5213 -                                                   TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
5214 -                                       }
5215 +                                       
5216                                 }
5217  
5218                                 dev->nFreeChunks += (dev->nChunksPerBlock - c);
5219 @@ -5569,7 +5635,7 @@ static int yaffs_Scan(yaffs_Device * dev
5220                                 /* PutChunkIntoFile checks for a clash (two data chunks with
5221                                  * the same chunkId).
5222                                  */
5223 -
5224 +                                
5225                                 if(!in)
5226                                         alloc_failed = 1;
5227  
5228 @@ -5577,11 +5643,11 @@ static int yaffs_Scan(yaffs_Device * dev
5229                                         if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1))
5230                                                 alloc_failed = 1;
5231                                 }
5232 -
5233 +                               
5234                                 endpos =
5235                                     (tags.chunkId - 1) * dev->nDataBytesPerChunk +
5236                                     tags.byteCount;
5237 -                               if (in &&
5238 +                               if (in && 
5239                                     in->variantType == YAFFS_OBJECT_TYPE_FILE
5240                                     && in->variant.fileVariant.scannedFileSize <
5241                                     endpos) {
5242 @@ -5613,7 +5679,7 @@ static int yaffs_Scan(yaffs_Device * dev
5243                                                               tags.objectId);
5244                                 if (in && in->variantType != oh->type) {
5245                                         /* This should not happen, but somehow
5246 -                                        * Wev'e ended up with an objectId that has been reused but not yet
5247 +                                        * Wev'e ended up with an objectId that has been reused but not yet 
5248                                          * deleted, and worse still it has changed type. Delete the old object.
5249                                          */
5250  
5251 @@ -5629,12 +5695,18 @@ static int yaffs_Scan(yaffs_Device * dev
5252  
5253                                 if(!in)
5254                                         alloc_failed = 1;
5255 -
5256 +                                       
5257                                 if (in && oh->shadowsObject > 0) {
5258 -                                       yaffs_HandleShadowedObject(dev,
5259 -                                                                  oh->
5260 -                                                                  shadowsObject,
5261 -                                                                  0);
5262 +                               
5263 +                                       struct yaffs_ShadowFixerStruct *fixer;
5264 +                                       fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct));
5265 +                                       if(fixer){
5266 +                                               fixer-> next = shadowFixerList;
5267 +                                               shadowFixerList = fixer;
5268 +                                               fixer->objectId = tags.objectId;
5269 +                                               fixer->shadowedId = oh->shadowsObject;
5270 +                                       }
5271 +                                       
5272                                 }
5273  
5274                                 if (in && in->valid) {
5275 @@ -5643,12 +5715,10 @@ static int yaffs_Scan(yaffs_Device * dev
5276                                         unsigned existingSerial = in->serial;
5277                                         unsigned newSerial = tags.serialNumber;
5278  
5279 -                                       if (dev->isYaffs2 ||
5280 -                                           ((existingSerial + 1) & 3) ==
5281 -                                           newSerial) {
5282 +                                       if (((existingSerial + 1) & 3) == newSerial) {
5283                                                 /* Use new one - destroy the exisiting one */
5284                                                 yaffs_DeleteChunk(dev,
5285 -                                                                 in->chunkId,
5286 +                                                                 in->hdrChunk,
5287                                                                   1, __LINE__);
5288                                                 in->valid = 0;
5289                                         } else {
5290 @@ -5681,7 +5751,8 @@ static int yaffs_Scan(yaffs_Device * dev
5291                                         in->yst_ctime = oh->yst_ctime;
5292                                         in->yst_rdev = oh->yst_rdev;
5293  #endif
5294 -                                       in->chunkId = chunk;
5295 +                                       in->hdrChunk = chunk;
5296 +                                       in->serial = tags.serialNumber;
5297  
5298                                 } else if (in && !in->valid) {
5299                                         /* we need to load this info */
5300 @@ -5705,7 +5776,8 @@ static int yaffs_Scan(yaffs_Device * dev
5301                                         in->yst_ctime = oh->yst_ctime;
5302                                         in->yst_rdev = oh->yst_rdev;
5303  #endif
5304 -                                       in->chunkId = chunk;
5305 +                                       in->hdrChunk = chunk;
5306 +                                       in->serial = tags.serialNumber;
5307  
5308                                         yaffs_SetObjectName(in, oh->name);
5309                                         in->dirty = 0;
5310 @@ -5720,13 +5792,13 @@ static int yaffs_Scan(yaffs_Device * dev
5311                                              YAFFS_OBJECT_TYPE_DIRECTORY);
5312                                         if (parent->variantType ==
5313                                             YAFFS_OBJECT_TYPE_UNKNOWN) {
5314 -                                               /* Set up as a directory */
5315 -                                               parent->variantType =
5316 -                                                   YAFFS_OBJECT_TYPE_DIRECTORY;
5317 -                                               INIT_LIST_HEAD(&parent->variant.
5318 -                                                              directoryVariant.
5319 -                                                              children);
5320 -                                       } else if (parent->variantType !=
5321 +                                                /* Set up as a directory */
5322 +                                                parent->variantType =
5323 +                                                    YAFFS_OBJECT_TYPE_DIRECTORY;
5324 +                                                YINIT_LIST_HEAD(&parent->variant.
5325 +                                                               directoryVariant.
5326 +                                                               children);
5327 +                                        } else if (parent->variantType !=
5328                                                    YAFFS_OBJECT_TYPE_DIRECTORY)
5329                                         {
5330                                                 /* Hoosterman, another problem....
5331 @@ -5735,8 +5807,7 @@ static int yaffs_Scan(yaffs_Device * dev
5332  
5333                                                 T(YAFFS_TRACE_ERROR,
5334                                                   (TSTR
5335 -                                                  ("yaffs tragedy: attempting to use non-directory as"
5336 -                                                   " a directory in scan. Put in lost+found."
5337 +                                                  ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
5338                                                     TENDSTR)));
5339                                                 parent = dev->lostNFoundDir;
5340                                         }
5341 @@ -5752,23 +5823,14 @@ static int yaffs_Scan(yaffs_Device * dev
5342                                          * Since we might scan a hardlink before its equivalent object is scanned
5343                                          * we put them all in a list.
5344                                          * After scanning is complete, we should have all the objects, so we run through this
5345 -                                        * list and fix up all the chains.
5346 +                                        * list and fix up all the chains.              
5347                                          */
5348  
5349                                         switch (in->variantType) {
5350 -                                       case YAFFS_OBJECT_TYPE_UNKNOWN:
5351 +                                       case YAFFS_OBJECT_TYPE_UNKNOWN: 
5352                                                 /* Todo got a problem */
5353                                                 break;
5354                                         case YAFFS_OBJECT_TYPE_FILE:
5355 -                                               if (dev->isYaffs2
5356 -                                                   && oh->isShrink) {
5357 -                                                       /* Prune back the shrunken chunks */
5358 -                                                       yaffs_PruneResizedChunks
5359 -                                                           (in, oh->fileSize);
5360 -                                                       /* Mark the block as having a shrinkHeader */
5361 -                                                       bi->hasShrinkHeader = 1;
5362 -                                               }
5363 -
5364                                                 if (dev->useHeaderFileSize)
5365  
5366                                                         in->variant.fileVariant.
5367 @@ -5778,20 +5840,20 @@ static int yaffs_Scan(yaffs_Device * dev
5368                                                 break;
5369                                         case YAFFS_OBJECT_TYPE_HARDLINK:
5370                                                 in->variant.hardLinkVariant.
5371 -                                                   equivalentObjectId =
5372 -                                                   oh->equivalentObjectId;
5373 -                                               in->hardLinks.next =
5374 -                                                   (struct list_head *)
5375 -                                                   hardList;
5376 -                                               hardList = in;
5377 -                                               break;
5378 +                                                    equivalentObjectId =
5379 +                                                    oh->equivalentObjectId;
5380 +                                                in->hardLinks.next =
5381 +                                                    (struct ylist_head *)
5382 +                                                    hardList;
5383 +                                                hardList = in;
5384 +                                                break;
5385                                         case YAFFS_OBJECT_TYPE_DIRECTORY:
5386                                                 /* Do nothing */
5387                                                 break;
5388                                         case YAFFS_OBJECT_TYPE_SPECIAL:
5389                                                 /* Do nothing */
5390                                                 break;
5391 -                                       case YAFFS_OBJECT_TYPE_SYMLINK:
5392 +                                       case YAFFS_OBJECT_TYPE_SYMLINK: 
5393                                                 in->variant.symLinkVariant.alias =
5394                                                     yaffs_CloneString(oh->alias);
5395                                                 if(!in->variant.symLinkVariant.alias)
5396 @@ -5799,10 +5861,12 @@ static int yaffs_Scan(yaffs_Device * dev
5397                                                 break;
5398                                         }
5399  
5400 -                                       if (parent == dev->deletedDir) {
5401 +/*
5402 +                                       if (parent == dev->deletedDir) {
5403                                                 yaffs_DestroyObject(in);
5404                                                 bi->hasShrinkHeader = 1;
5405                                         }
5406 +*/
5407                                 }
5408                         }
5409                 }
5410 @@ -5823,35 +5887,36 @@ static int yaffs_Scan(yaffs_Device * dev
5411  
5412         }
5413  
5414 -       if (blockIndex) {
5415 -               YFREE(blockIndex);
5416 -       }
5417 -
5418 -
5419 +       
5420         /* Ok, we've done all the scanning.
5421          * Fix up the hard link chains.
5422 -        * We should now have scanned all the objects, now it's time to add these
5423 +        * We should now have scanned all the objects, now it's time to add these 
5424          * hardlinks.
5425          */
5426  
5427         yaffs_HardlinkFixup(dev,hardList);
5428 -
5429 -       /* Handle the unlinked files. Since they were left in an unlinked state we should
5430 -        * just delete them.
5431 -        */
5432 +       
5433 +       /* Fix up any shadowed objects */
5434         {
5435 -               struct list_head *i;
5436 -               struct list_head *n;
5437 -
5438 -               yaffs_Object *l;
5439 -               /* Soft delete all the unlinked files */
5440 -               list_for_each_safe(i, n,
5441 -                                  &dev->unlinkedDir->variant.directoryVariant.
5442 -                                  children) {
5443 -                       if (i) {
5444 -                               l = list_entry(i, yaffs_Object, siblings);
5445 -                               yaffs_DestroyObject(l);
5446 +               struct yaffs_ShadowFixerStruct *fixer;
5447 +               yaffs_Object *obj;
5448 +               
5449 +               while(shadowFixerList){
5450 +                       fixer = shadowFixerList;
5451 +                       shadowFixerList = fixer->next;
5452 +                       /* Complete the rename transaction by deleting the shadowed object
5453 +                        * then setting the object header to unshadowed.
5454 +                        */
5455 +                       obj = yaffs_FindObjectByNumber(dev,fixer->shadowedId);
5456 +                       if(obj)
5457 +                               yaffs_DestroyObject(obj);
5458 +       
5459 +                       obj = yaffs_FindObjectByNumber(dev,fixer->objectId);
5460 +                       if(obj){
5461 +                               yaffs_UpdateObjectHeader(obj,NULL,1,0,0);
5462                         }
5463 +                       
5464 +                       YFREE(fixer);
5465                 }
5466         }
5467  
5468 @@ -5860,9 +5925,9 @@ static int yaffs_Scan(yaffs_Device * dev
5469         if(alloc_failed){
5470                 return YAFFS_FAIL;
5471         }
5472 -
5473 +       
5474         T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
5475 -
5476 +       
5477  
5478         return YAFFS_OK;
5479  }
5480 @@ -5871,25 +5936,27 @@ static void yaffs_CheckObjectDetailsLoad
5481  {
5482         __u8 *chunkData;
5483         yaffs_ObjectHeader *oh;
5484 -       yaffs_Device *dev = in->myDev;
5485 +       yaffs_Device *dev;
5486         yaffs_ExtendedTags tags;
5487         int result;
5488         int alloc_failed = 0;
5489  
5490         if(!in)
5491                 return;
5492 -
5493 +               
5494 +       dev = in->myDev;
5495 +               
5496  #if 0
5497         T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
5498                 in->objectId,
5499                 in->lazyLoaded ? "not yet" : "already"));
5500  #endif
5501  
5502 -       if(in->lazyLoaded){
5503 +       if(in->lazyLoaded && in->hdrChunk > 0){
5504                 in->lazyLoaded = 0;
5505                 chunkData = yaffs_GetTempBuffer(dev, __LINE__);
5506  
5507 -               result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
5508 +               result = yaffs_ReadChunkWithTagsFromNAND(dev,in->hdrChunk,chunkData,&tags);
5509                 oh = (yaffs_ObjectHeader *) chunkData;
5510  
5511                 in->yst_mode = oh->yst_mode;
5512 @@ -5907,17 +5974,17 @@ static void yaffs_CheckObjectDetailsLoad
5513                 in->yst_mtime = oh->yst_mtime;
5514                 in->yst_ctime = oh->yst_ctime;
5515                 in->yst_rdev = oh->yst_rdev;
5516 -
5517 +               
5518  #endif
5519                 yaffs_SetObjectName(in, oh->name);
5520 -
5521 +               
5522                 if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){
5523                          in->variant.symLinkVariant.alias =
5524                                                     yaffs_CloneString(oh->alias);
5525                         if(!in->variant.symLinkVariant.alias)
5526                                 alloc_failed = 1; /* Not returned to caller */
5527                 }
5528 -
5529 +                                                   
5530                 yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
5531         }
5532  }
5533 @@ -5938,20 +6005,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5534         yaffs_BlockState state;
5535         yaffs_Object *hardList = NULL;
5536         yaffs_BlockInfo *bi;
5537 -       int sequenceNumber;
5538 +       __u32 sequenceNumber;
5539         yaffs_ObjectHeader *oh;
5540         yaffs_Object *in;
5541         yaffs_Object *parent;
5542         int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
5543         int itsUnlinked;
5544         __u8 *chunkData;
5545 -
5546 +       
5547         int fileSize;
5548         int isShrink;
5549         int foundChunksInBlock;
5550         int equivalentObjectId;
5551         int alloc_failed = 0;
5552 -
5553 +       
5554  
5555         yaffs_BlockIndex *blockIndex = NULL;
5556         int altBlockIndex = 0;
5557 @@ -5971,20 +6038,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5558         dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
5559  
5560         blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
5561 -
5562 +       
5563         if(!blockIndex) {
5564                 blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
5565                 altBlockIndex = 1;
5566         }
5567 -
5568 +       
5569         if(!blockIndex) {
5570                 T(YAFFS_TRACE_SCAN,
5571                   (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
5572                 return YAFFS_FAIL;
5573         }
5574 -
5575 +       
5576         dev->blocksInCheckpoint = 0;
5577 -
5578 +       
5579         chunkData = yaffs_GetTempBuffer(dev, __LINE__);
5580  
5581         /* Scan all the blocks to determine their state */
5582 @@ -6001,15 +6068,15 @@ static int yaffs_ScanBackwards(yaffs_Dev
5583  
5584                 if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
5585                         bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
5586 -
5587 +                       
5588                 T(YAFFS_TRACE_SCAN_DEBUG,
5589                   (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
5590                    state, sequenceNumber));
5591  
5592 -
5593 +               
5594                 if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
5595                         dev->blocksInCheckpoint++;
5596 -
5597 +                       
5598                 } else if (state == YAFFS_BLOCK_STATE_DEAD) {
5599                         T(YAFFS_TRACE_BAD_BLOCKS,
5600                           (TSTR("block %d is bad" TENDSTR), blk));
5601 @@ -6021,8 +6088,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5602                 } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
5603  
5604                         /* Determine the highest sequence number */
5605 -                       if (dev->isYaffs2 &&
5606 -                           sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5607 +                       if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5608                             sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
5609  
5610                                 blockIndex[nBlocksToScan].seq = sequenceNumber;
5611 @@ -6033,7 +6099,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5612                                 if (sequenceNumber >= dev->sequenceNumber) {
5613                                         dev->sequenceNumber = sequenceNumber;
5614                                 }
5615 -                       } else if (dev->isYaffs2) {
5616 +                       } else {
5617                                 /* TODO: Nasty sequence number! */
5618                                 T(YAFFS_TRACE_SCAN,
5619                                   (TSTR
5620 @@ -6053,12 +6119,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
5621  
5622         /* Sort the blocks */
5623  #ifndef CONFIG_YAFFS_USE_OWN_SORT
5624 -       yaffs_qsort(blockIndex, nBlocksToScan,
5625 -               sizeof(yaffs_BlockIndex), ybicmp);
5626 +       {
5627 +               /* Use qsort now. */
5628 +               yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
5629 +       }
5630  #else
5631         {
5632                 /* Dungy old bubble sort... */
5633 -
5634 +               
5635                 yaffs_BlockIndex temp;
5636                 int i;
5637                 int j;
5638 @@ -6094,22 +6162,22 @@ static int yaffs_ScanBackwards(yaffs_Dev
5639                 blk = blockIndex[blockIterator].block;
5640  
5641                 bi = yaffs_GetBlockInfo(dev, blk);
5642 -
5643 -
5644 +               
5645 +               
5646                 state = bi->blockState;
5647  
5648                 deleted = 0;
5649  
5650                 /* For each chunk in each block that needs scanning.... */
5651                 foundChunksInBlock = 0;
5652 -               for (c = dev->nChunksPerBlock - 1;
5653 +               for (c = dev->nChunksPerBlock - 1; 
5654                      !alloc_failed && c >= 0 &&
5655                      (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
5656                       state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
5657 -                       /* Scan backwards...
5658 +                       /* Scan backwards... 
5659                          * Read the tags and decide what to do
5660                          */
5661 -
5662 +                       
5663                         chunk = blk * dev->nChunksPerBlock + c;
5664  
5665                         result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
5666 @@ -6123,14 +6191,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
5667                                  * it is a chunk that was skipped due to failing the erased
5668                                  * check. Just skip it so that it can be deleted.
5669                                  * But, more typically, We get here when this is an unallocated
5670 -                                * chunk and his means that either the block is empty or
5671 +                                * chunk and his means that either the block is empty or 
5672                                  * this is the one being allocated from
5673                                  */
5674  
5675                                 if(foundChunksInBlock)
5676                                 {
5677                                         /* This is a chunk that was skipped due to failing the erased check */
5678 -
5679 +                                       
5680                                 } else if (c == 0) {
5681                                         /* We're looking at the first chunk in the block so the block is unused */
5682                                         state = YAFFS_BLOCK_STATE_EMPTY;
5683 @@ -6140,7 +6208,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5684                                             state == YAFFS_BLOCK_STATE_ALLOCATING) {
5685                                                 if(dev->sequenceNumber == bi->sequenceNumber) {
5686                                                         /* this is the block being allocated from */
5687 -
5688 +                                               
5689                                                         T(YAFFS_TRACE_SCAN,
5690                                                           (TSTR
5691                                                            (" Allocating from %d %d"
5692 @@ -6149,34 +6217,41 @@ static int yaffs_ScanBackwards(yaffs_Dev
5693                                                         state = YAFFS_BLOCK_STATE_ALLOCATING;
5694                                                         dev->allocationBlock = blk;
5695                                                         dev->allocationPage = c;
5696 -                                                       dev->allocationBlockFinder = blk;
5697 +                                                       dev->allocationBlockFinder = blk;       
5698                                                 }
5699                                                 else {
5700                                                         /* This is a partially written block that is not
5701                                                          * the current allocation block. This block must have
5702                                                          * had a write failure, so set up for retirement.
5703                                                          */
5704 -
5705 -                                                        bi->needsRetiring = 1;
5706 +                                                 
5707 +                                                        /* bi->needsRetiring = 1; ??? TODO */
5708                                                          bi->gcPrioritise = 1;
5709 -
5710 +                                                                                                        
5711                                                          T(YAFFS_TRACE_ALWAYS,
5712 -                                                        (TSTR("Partially written block %d being set for retirement" TENDSTR),
5713 +                                                        (TSTR("Partially written block %d detected" TENDSTR),
5714                                                          blk));
5715                                                 }
5716  
5717                                         }
5718 -
5719 +                                        
5720                                 }
5721  
5722                                 dev->nFreeChunks++;
5723 +                               
5724 +                       } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){
5725 +                               T(YAFFS_TRACE_SCAN,
5726 +                                 (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR),
5727 +                                 blk, c));
5728  
5729 -                       } else if (tags.chunkId > 0) {
5730 +                                 dev->nFreeChunks++;
5731 +
5732 +                       }else if (tags.chunkId > 0) {
5733                                 /* chunkId > 0 so it is a data chunk... */
5734                                 unsigned int endpos;
5735                                 __u32 chunkBase =
5736                                     (tags.chunkId - 1) * dev->nDataBytesPerChunk;
5737 -
5738 +                                                               
5739                                 foundChunksInBlock = 1;
5740  
5741  
5742 @@ -6191,7 +6266,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5743                                         /* Out of memory */
5744                                         alloc_failed = 1;
5745                                 }
5746 -
5747 +                               
5748                                 if (in &&
5749                                     in->variantType == YAFFS_OBJECT_TYPE_FILE
5750                                     && chunkBase <
5751 @@ -6202,14 +6277,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
5752                                                 alloc_failed = 1;
5753                                         }
5754  
5755 -                                       /* File size is calculated by looking at the data chunks if we have not
5756 +                                       /* File size is calculated by looking at the data chunks if we have not 
5757                                          * seen an object header yet. Stop this practice once we find an object header.
5758                                          */
5759                                         endpos =
5760                                             (tags.chunkId -
5761                                              1) * dev->nDataBytesPerChunk +
5762                                             tags.byteCount;
5763 -
5764 +                                           
5765                                         if (!in->valid &&       /* have not got an object header yet */
5766                                             in->variant.fileVariant.
5767                                             scannedFileSize < endpos) {
5768 @@ -6255,7 +6330,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5769                                     ) {
5770  
5771                                         /* If we don't have  valid info then we need to read the chunk
5772 -                                        * TODO In future we can probably defer reading the chunk and
5773 +                                        * TODO In future we can probably defer reading the chunk and 
5774                                          * living with invalid data until needed.
5775                                          */
5776  
5777 @@ -6265,6 +6340,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
5778                                                                         NULL);
5779  
5780                                         oh = (yaffs_ObjectHeader *) chunkData;
5781 +                                       
5782 +                                       if(dev->inbandTags){
5783 +                                               /* Fix up the header if they got corrupted by inband tags */
5784 +                                               oh->shadowsObject = oh->inbandShadowsObject;
5785 +                                               oh->isShrink = oh->inbandIsShrink;
5786 +                                       }
5787  
5788                                         if (!in)
5789                                                 in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
5790 @@ -6275,20 +6356,19 @@ static int yaffs_ScanBackwards(yaffs_Dev
5791                                         /* TODO Hoosterman we have a problem! */
5792                                         T(YAFFS_TRACE_ERROR,
5793                                           (TSTR
5794 -                                          ("yaffs tragedy: Could not make object for object  %d  "
5795 -                                           "at chunk %d during scan"
5796 +                                          ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"
5797                                             TENDSTR), tags.objectId, chunk));
5798  
5799                                 }
5800  
5801                                 if (in->valid) {
5802                                         /* We have already filled this one.
5803 -                                        * We have a duplicate that will be discarded, but
5804 +                                        * We have a duplicate that will be discarded, but 
5805                                          * we first have to suck out resize info if it is a file.
5806                                          */
5807  
5808 -                                       if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
5809 -                                            ((oh &&
5810 +                                       if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && 
5811 +                                            ((oh && 
5812                                                oh-> type == YAFFS_OBJECT_TYPE_FILE)||
5813                                               (tags.extraHeaderInfoAvailable  &&
5814                                                tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
5815 @@ -6300,7 +6380,9 @@ static int yaffs_ScanBackwards(yaffs_Dev
5816                                                     (oh) ? oh->
5817                                                     parentObjectId : tags.
5818                                                     extraParentObjectId;
5819 -                                               unsigned isShrink =
5820 +                                               
5821 +                                               
5822 +                                               isShrink =
5823                                                     (oh) ? oh->isShrink : tags.
5824                                                     extraIsShrinkHeader;
5825  
5826 @@ -6339,7 +6421,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5827                                      YAFFS_OBJECTID_LOSTNFOUND)) {
5828                                         /* We only load some info, don't fiddle with directory structure */
5829                                         in->valid = 1;
5830 -
5831 +                                       
5832                                         if(oh) {
5833                                                 in->variantType = oh->type;
5834  
5835 @@ -6358,20 +6440,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5836                                                 in->yst_mtime = oh->yst_mtime;
5837                                                 in->yst_ctime = oh->yst_ctime;
5838                                                 in->yst_rdev = oh->yst_rdev;
5839 -
5840 +               
5841  #endif
5842                                         } else {
5843                                                 in->variantType = tags.extraObjectType;
5844                                                 in->lazyLoaded = 1;
5845                                         }
5846  
5847 -                                       in->chunkId = chunk;
5848 +                                       in->hdrChunk = chunk;
5849  
5850                                 } else if (!in->valid) {
5851                                         /* we need to load this info */
5852  
5853                                         in->valid = 1;
5854 -                                       in->chunkId = chunk;
5855 +                                       in->hdrChunk = chunk;
5856  
5857                                         if(oh) {
5858                                                 in->variantType = oh->type;
5859 @@ -6393,12 +6475,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
5860                                                 in->yst_rdev = oh->yst_rdev;
5861  #endif
5862  
5863 -                                               if (oh->shadowsObject > 0)
5864 +                                               if (oh->shadowsObject > 0) 
5865                                                         yaffs_HandleShadowedObject(dev,
5866                                                                            oh->
5867                                                                            shadowsObject,
5868                                                                            1);
5869 -
5870 +                                       
5871  
5872                                                 yaffs_SetObjectName(in, oh->name);
5873                                                 parent =
5874 @@ -6431,13 +6513,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
5875  
5876                                         if (parent->variantType ==
5877                                             YAFFS_OBJECT_TYPE_UNKNOWN) {
5878 -                                               /* Set up as a directory */
5879 -                                               parent->variantType =
5880 -                                                   YAFFS_OBJECT_TYPE_DIRECTORY;
5881 -                                               INIT_LIST_HEAD(&parent->variant.
5882 -                                                              directoryVariant.
5883 -                                                              children);
5884 -                                       } else if (parent->variantType !=
5885 +                                                /* Set up as a directory */
5886 +                                                parent->variantType =
5887 +                                                    YAFFS_OBJECT_TYPE_DIRECTORY;
5888 +                                                YINIT_LIST_HEAD(&parent->variant.
5889 +                                                               directoryVariant.
5890 +                                                               children);
5891 +                                        } else if (parent->variantType !=
5892                                                    YAFFS_OBJECT_TYPE_DIRECTORY)
5893                                         {
5894                                                 /* Hoosterman, another problem....
5895 @@ -6446,8 +6528,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5896  
5897                                                 T(YAFFS_TRACE_ERROR,
5898                                                   (TSTR
5899 -                                                  ("yaffs tragedy: attempting to use non-directory as"
5900 -                                                   " a directory in scan. Put in lost+found."
5901 +                                                  ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
5902                                                     TENDSTR)));
5903                                                 parent = dev->lostNFoundDir;
5904                                         }
5905 @@ -6466,11 +6547,11 @@ static int yaffs_ScanBackwards(yaffs_Dev
5906                                          * Since we might scan a hardlink before its equivalent object is scanned
5907                                          * we put them all in a list.
5908                                          * After scanning is complete, we should have all the objects, so we run
5909 -                                        * through this list and fix up all the chains.
5910 +                                        * through this list and fix up all the chains.              
5911                                          */
5912  
5913                                         switch (in->variantType) {
5914 -                                       case YAFFS_OBJECT_TYPE_UNKNOWN:
5915 +                                       case YAFFS_OBJECT_TYPE_UNKNOWN: 
5916                                                 /* Todo got a problem */
5917                                                 break;
5918                                         case YAFFS_OBJECT_TYPE_FILE:
5919 @@ -6479,7 +6560,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5920                                                     scannedFileSize < fileSize) {
5921                                                         /* This covers the case where the file size is greater
5922                                                          * than where the data is
5923 -                                                        * This will happen if the file is resized to be larger
5924 +                                                        * This will happen if the file is resized to be larger 
5925                                                          * than its current data extents.
5926                                                          */
5927                                                         in->variant.fileVariant.fileSize = fileSize;
5928 @@ -6495,13 +6576,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
5929                                                 break;
5930                                         case YAFFS_OBJECT_TYPE_HARDLINK:
5931                                                 if(!itsUnlinked) {
5932 -                                                 in->variant.hardLinkVariant.equivalentObjectId =
5933 -                                                   equivalentObjectId;
5934 -                                                 in->hardLinks.next =
5935 -                                                   (struct list_head *) hardList;
5936 -                                                 hardList = in;
5937 -                                               }
5938 -                                               break;
5939 +                                                  in->variant.hardLinkVariant.equivalentObjectId =
5940 +                                                    equivalentObjectId;
5941 +                                                  in->hardLinks.next =
5942 +                                                    (struct ylist_head *) hardList;
5943 +                                                  hardList = in;
5944 +                                                }
5945 +                                                break;
5946                                         case YAFFS_OBJECT_TYPE_DIRECTORY:
5947                                                 /* Do nothing */
5948                                                 break;
5949 @@ -6520,7 +6601,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5950                                         }
5951  
5952                                 }
5953 -
5954 +                               
5955                         }
5956  
5957                 } /* End of scanning for each chunk */
5958 @@ -6541,72 +6622,128 @@ static int yaffs_ScanBackwards(yaffs_Dev
5959  
5960         }
5961  
5962 -       if (altBlockIndex)
5963 +       if (altBlockIndex) 
5964                 YFREE_ALT(blockIndex);
5965         else
5966                 YFREE(blockIndex);
5967 -
5968 +       
5969         /* Ok, we've done all the scanning.
5970          * Fix up the hard link chains.
5971 -        * We should now have scanned all the objects, now it's time to add these
5972 +        * We should now have scanned all the objects, now it's time to add these 
5973          * hardlinks.
5974          */
5975         yaffs_HardlinkFixup(dev,hardList);
5976 +       
5977  
5978 +       yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
5979 +       
5980 +       if(alloc_failed){
5981 +               return YAFFS_FAIL;
5982 +       }
5983  
5984 -       /*
5985 -       *  Sort out state of unlinked and deleted objects.
5986 -       */
5987 -       {
5988 -               struct list_head *i;
5989 -               struct list_head *n;
5990 +       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
5991  
5992 -               yaffs_Object *l;
5993 +       return YAFFS_OK;
5994 +}
5995  
5996 -               /* Soft delete all the unlinked files */
5997 -               list_for_each_safe(i, n,
5998 -                                  &dev->unlinkedDir->variant.directoryVariant.
5999 -                                  children) {
6000 -                       if (i) {
6001 -                               l = list_entry(i, yaffs_Object, siblings);
6002 -                               yaffs_DestroyObject(l);
6003 -                       }
6004 -               }
6005 +/*------------------------------  Directory Functions ----------------------------- */
6006  
6007 -               /* Soft delete all the deletedDir files */
6008 -               list_for_each_safe(i, n,
6009 -                                  &dev->deletedDir->variant.directoryVariant.
6010 -                                  children) {
6011 -                       if (i) {
6012 -                               l = list_entry(i, yaffs_Object, siblings);
6013 -                               yaffs_DestroyObject(l);
6014 +static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj)
6015 +{
6016 +        struct ylist_head *lh;
6017 +        yaffs_Object *listObj;
6018 +        
6019 +        int count = 0;
6020  
6021 -                       }
6022 -               }
6023 +       if(!obj){
6024 +               T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR)));
6025 +               YBUG();
6026         }
6027  
6028 -       yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
6029 +        if(yaffs_SkipVerification(obj->myDev))
6030 +                return;
6031  
6032 -       if(alloc_failed){
6033 -               return YAFFS_FAIL;
6034 +       if(!obj->parent){
6035 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR)));
6036 +               YBUG();
6037 +       }
6038 +               
6039 +       if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
6040 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR)));
6041 +               YBUG();
6042 +       }
6043 +       
6044 +        /* Iterate through the objects in each hash entry */
6045 +         
6046 +        ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) {
6047 +               if (lh) {
6048 +                        listObj = ylist_entry(lh, yaffs_Object, siblings);
6049 +                       yaffs_VerifyObject(listObj);
6050 +                       if(obj == listObj)
6051 +                               count ++;
6052 +                }
6053 +        }
6054 +        
6055 +        if(count != 1){
6056 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR),count));
6057 +               YBUG();
6058         }
6059  
6060 -       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
6061 +}
6062  
6063 -       return YAFFS_OK;
6064 +static void yaffs_VerifyDirectory(yaffs_Object *directory)
6065 +{
6066 +
6067 +        struct ylist_head *lh;
6068 +        yaffs_Object *listObj;
6069 +        
6070 +       if(!directory)
6071 +               YBUG();
6072 +
6073 +        if(yaffs_SkipFullVerification(directory->myDev))
6074 +                return;
6075 +
6076 +               
6077 +       if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
6078 +               T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR),directory->variantType));
6079 +               YBUG();
6080 +       }
6081 +       
6082 +        /* Iterate through the objects in each hash entry */
6083 +         
6084 +        ylist_for_each(lh, &directory->variant.directoryVariant.children) {
6085 +               if (lh) {
6086 +                        listObj = ylist_entry(lh, yaffs_Object, siblings);
6087 +                       if(listObj->parent != directory){
6088 +                               T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR),listObj->parent));
6089 +                               YBUG();
6090 +                       }
6091 +                       yaffs_VerifyObjectInDirectory(listObj);
6092 +                }
6093 +        }
6094 +        
6095  }
6096  
6097 -/*------------------------------  Directory Functions ----------------------------- */
6098  
6099  static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
6100  {
6101         yaffs_Device *dev = obj->myDev;
6102 +       yaffs_Object *parent;
6103 +       
6104 +        yaffs_VerifyObjectInDirectory(obj);
6105 +       parent = obj->parent;
6106 +       
6107 +       yaffs_VerifyDirectory(parent);
6108 +
6109 +        if(dev && dev->removeObjectCallback)
6110 +                dev->removeObjectCallback(obj);
6111 +
6112 +           
6113 +        ylist_del_init(&obj->siblings);
6114 +        obj->parent = NULL;
6115  
6116 -       if(dev && dev->removeObjectCallback)
6117 -               dev->removeObjectCallback(obj);
6118 +       yaffs_VerifyDirectory(parent);
6119  
6120 -       list_del_init(&obj->siblings);
6121 -       obj->parent = NULL;
6122  }
6123  
6124  
6125 @@ -6629,35 +6766,46 @@ static void yaffs_AddObjectToDirectory(y
6126                 YBUG();
6127         }
6128  
6129 -       if (obj->siblings.prev == NULL) {
6130 -               /* Not initialised */
6131 -               INIT_LIST_HEAD(&obj->siblings);
6132 -
6133 -       } else if (!list_empty(&obj->siblings)) {
6134 -               /* If it is holed up somewhere else, un hook it */
6135 -               yaffs_RemoveObjectFromDirectory(obj);
6136 -       }
6137 -       /* Now add it */
6138 -       list_add(&obj->siblings, &directory->variant.directoryVariant.children);
6139 -       obj->parent = directory;
6140 +        if (obj->siblings.prev == NULL) {
6141 +                /* Not initialised */
6142 +                YBUG();
6143 +
6144 +        } else if (ylist_empty(&obj->siblings)) {
6145 +               YBUG();
6146 +        } 
6147 +
6148  
6149 -       if (directory == obj->myDev->unlinkedDir
6150 +       yaffs_VerifyDirectory(directory);
6151 +
6152 +       yaffs_RemoveObjectFromDirectory(obj);
6153 +        
6154 +        
6155 +        /* Now add it */
6156 +        ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
6157 +        obj->parent = directory;
6158 +
6159 +        if (directory == obj->myDev->unlinkedDir
6160             || directory == obj->myDev->deletedDir) {
6161                 obj->unlinked = 1;
6162                 obj->myDev->nUnlinkedFiles++;
6163                 obj->renameAllowed = 0;
6164         }
6165 +
6166 +       yaffs_VerifyDirectory(directory);
6167 +        yaffs_VerifyObjectInDirectory(obj);
6168 +
6169 +
6170  }
6171  
6172  yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
6173                                      const YCHAR * name)
6174  {
6175 -       int sum;
6176 +        int sum;
6177  
6178 -       struct list_head *i;
6179 -       YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
6180 +        struct ylist_head *i;
6181 +        YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
6182  
6183 -       yaffs_Object *l;
6184 +        yaffs_Object *l;
6185  
6186         if (!name) {
6187                 return NULL;
6188 @@ -6677,22 +6825,24 @@ yaffs_Object *yaffs_FindObjectByName(yaf
6189                 YBUG();
6190         }
6191  
6192 -       sum = yaffs_CalcNameSum(name);
6193 +        sum = yaffs_CalcNameSum(name);
6194  
6195 -       list_for_each(i, &directory->variant.directoryVariant.children) {
6196 -               if (i) {
6197 -                       l = list_entry(i, yaffs_Object, siblings);
6198 -
6199 -                       yaffs_CheckObjectDetailsLoaded(l);
6200 +        ylist_for_each(i, &directory->variant.directoryVariant.children) {
6201 +                if (i) {
6202 +                        l = ylist_entry(i, yaffs_Object, siblings);
6203 +                        
6204 +                        if(l->parent != directory)
6205 +                               YBUG();
6206 +                        
6207 +                        yaffs_CheckObjectDetailsLoaded(l);
6208  
6209                         /* Special case for lost-n-found */
6210                         if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
6211                                 if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
6212                                         return l;
6213                                 }
6214 -                       } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
6215 -                       {
6216 -                               /* LostnFound cunk called Objxxx
6217 +                       } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0){
6218 +                               /* LostnFound chunk called Objxxx
6219                                  * Do a real check
6220                                  */
6221                                 yaffs_GetObjectName(l, buffer,
6222 @@ -6711,12 +6861,12 @@ yaffs_Object *yaffs_FindObjectByName(yaf
6223  
6224  #if 0
6225  int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
6226 -                                  int (*fn) (yaffs_Object *))
6227 +                                   int (*fn) (yaffs_Object *))
6228  {
6229 -       struct list_head *i;
6230 -       yaffs_Object *l;
6231 +        struct ylist_head *i;
6232 +        yaffs_Object *l;
6233  
6234 -       if (!theDir) {
6235 +        if (!theDir) {
6236                 T(YAFFS_TRACE_ALWAYS,
6237                   (TSTR
6238                    ("tragedy: yaffs_FindObjectByName: null pointer directory"
6239 @@ -6727,15 +6877,15 @@ int yaffs_ApplyToDirectoryChildren(yaffs
6240                 T(YAFFS_TRACE_ALWAYS,
6241                   (TSTR
6242                    ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
6243 -               YBUG();
6244 -       }
6245 +                YBUG();
6246 +        }
6247  
6248 -       list_for_each(i, &theDir->variant.directoryVariant.children) {
6249 -               if (i) {
6250 -                       l = list_entry(i, yaffs_Object, siblings);
6251 -                       if (l && !fn(l)) {
6252 -                               return YAFFS_FAIL;
6253 -                       }
6254 +        ylist_for_each(i, &theDir->variant.directoryVariant.children) {
6255 +                if (i) {
6256 +                        l = ylist_entry(i, yaffs_Object, siblings);
6257 +                        if (l && !fn(l)) {
6258 +                                return YAFFS_FAIL;
6259 +                        }
6260                 }
6261         }
6262  
6263 @@ -6762,16 +6912,25 @@ yaffs_Object *yaffs_GetEquivalentObject(
6264  int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
6265  {
6266         memset(name, 0, buffSize * sizeof(YCHAR));
6267 -
6268 +       
6269         yaffs_CheckObjectDetailsLoaded(obj);
6270  
6271         if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
6272                 yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
6273 -       } else if (obj->chunkId <= 0) {
6274 +       } else if (obj->hdrChunk <= 0) {
6275                 YCHAR locName[20];
6276 +               YCHAR numString[20];
6277 +               YCHAR *x = &numString[19];
6278 +               unsigned v = obj->objectId;
6279 +               numString[19] = 0;
6280 +               while(v>0){
6281 +                       x--;
6282 +                       *x = '0' + (v % 10);
6283 +                       v /= 10;
6284 +               }
6285                 /* make up a name */
6286 -               yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
6287 -                             obj->objectId);
6288 +               yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX);
6289 +               yaffs_strcat(locName,x);
6290                 yaffs_strncpy(name, locName, buffSize - 1);
6291  
6292         }
6293 @@ -6788,9 +6947,9 @@ int yaffs_GetObjectName(yaffs_Object * o
6294  
6295                 memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
6296  
6297 -               if (obj->chunkId >= 0) {
6298 +               if (obj->hdrChunk > 0) {
6299                         result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
6300 -                                                       obj->chunkId, buffer,
6301 +                                                       obj->hdrChunk, buffer,
6302                                                         NULL);
6303                 }
6304                 yaffs_strncpy(name, oh->name, buffSize - 1);
6305 @@ -6820,16 +6979,16 @@ int yaffs_GetObjectFileLength(yaffs_Obje
6306  
6307  int yaffs_GetObjectLinkCount(yaffs_Object * obj)
6308  {
6309 -       int count = 0;
6310 -       struct list_head *i;
6311 +        int count = 0;
6312 +        struct ylist_head *i;
6313  
6314 -       if (!obj->unlinked) {
6315 -               count++;        /* the object itself */
6316 -       }
6317 -       list_for_each(i, &obj->hardLinks) {
6318 -               count++;        /* add the hard links; */
6319 -       }
6320 -       return count;
6321 +        if (!obj->unlinked) {
6322 +                count++;        /* the object itself */
6323 +        }
6324 +        ylist_for_each(i, &obj->hardLinks) {
6325 +                count++;        /* add the hard links; */
6326 +        }
6327 +        return count;
6328  
6329  }
6330  
6331 @@ -6951,7 +7110,7 @@ int yaffs_DumpObject(yaffs_Object * obj)
6332            ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
6333             " chunk %d type %d size %d\n"
6334             TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
6335 -          obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
6336 +          obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk,
6337            yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
6338  
6339         return YAFFS_OK;
6340 @@ -6994,13 +7153,13 @@ static int yaffs_CheckDevFunctions(const
6341  static int yaffs_CreateInitialDirectories(yaffs_Device *dev)
6342  {
6343         /* Initialise the unlinked, deleted, root and lost and found directories */
6344 -
6345 +       
6346         dev->lostNFoundDir = dev->rootDir =  NULL;
6347         dev->unlinkedDir = dev->deletedDir = NULL;
6348  
6349         dev->unlinkedDir =
6350             yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
6351 -
6352 +       
6353         dev->deletedDir =
6354             yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
6355  
6356 @@ -7010,12 +7169,12 @@ static int yaffs_CreateInitialDirectorie
6357         dev->lostNFoundDir =
6358             yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
6359                                       YAFFS_LOSTNFOUND_MODE | S_IFDIR);
6360 -
6361 +       
6362         if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){
6363                 yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
6364                 return YAFFS_OK;
6365         }
6366 -
6367 +       
6368         return YAFFS_FAIL;
6369  }
6370  
6371 @@ -7039,6 +7198,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
6372         dev->blockOffset = 0;
6373         dev->chunkOffset = 0;
6374         dev->nFreeChunks = 0;
6375 +       
6376 +       dev->gcBlock = -1;
6377  
6378         if (dev->startBlock == 0) {
6379                 dev->internalStartBlock = dev->startBlock + 1;
6380 @@ -7049,18 +7210,19 @@ int yaffs_GutsInitialise(yaffs_Device * 
6381  
6382         /* Check geometry parameters. */
6383  
6384 -       if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
6385 -           (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
6386 -            dev->nChunksPerBlock < 2 ||
6387 -            dev->nReservedBlocks < 2 ||
6388 -            dev->internalStartBlock <= 0 ||
6389 -            dev->internalEndBlock <= 0 ||
6390 +       if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || 
6391 +           (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || 
6392 +           (dev->inbandTags && !dev->isYaffs2 ) ||
6393 +            dev->nChunksPerBlock < 2 || 
6394 +            dev->nReservedBlocks < 2 || 
6395 +            dev->internalStartBlock <= 0 || 
6396 +            dev->internalEndBlock <= 0 || 
6397              dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)      // otherwise it is too small
6398             ) {
6399                 T(YAFFS_TRACE_ALWAYS,
6400                   (TSTR
6401 -                  ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
6402 -                   TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
6403 +                  ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
6404 +                   TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
6405                 return YAFFS_FAIL;
6406         }
6407  
6408 @@ -7069,6 +7231,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
6409                   (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
6410                 return YAFFS_FAIL;
6411         }
6412 +       
6413 +       /* Sort out space for inband tags, if required */
6414 +       if(dev->inbandTags)
6415 +               dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
6416 +       else 
6417 +               dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
6418  
6419         /* Got the right mix of functions? */
6420         if (!yaffs_CheckDevFunctions(dev)) {
6421 @@ -7097,41 +7265,28 @@ int yaffs_GutsInitialise(yaffs_Device * 
6422  
6423         dev->isMounted = 1;
6424  
6425 -
6426 -
6427         /* OK now calculate a few things for the device */
6428 -
6429 +       
6430         /*
6431 -        *  Calculate all the chunk size manipulation numbers:
6432 +        *  Calculate all the chunk size manipulation numbers:   
6433          */
6434 -        /* Start off assuming it is a power of 2 */
6435 -        dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
6436 -        dev->chunkMask = (1<<dev->chunkShift) - 1;
6437 -
6438 -        if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
6439 -               /* Yes it is a power of 2, disable crumbs */
6440 -               dev->crumbMask = 0;
6441 -               dev->crumbShift = 0;
6442 -               dev->crumbsPerChunk = 0;
6443 -        } else {
6444 -               /* Not a power of 2, use crumbs instead */
6445 -               dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
6446 -               dev->crumbMask = (1<<dev->crumbShift)-1;
6447 -               dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
6448 -               dev->chunkShift = 0;
6449 -               dev->chunkMask = 0;
6450 -       }
6451 -
6452 -
6453 +       x = dev->nDataBytesPerChunk;
6454 +       /* We always use dev->chunkShift and dev->chunkDiv */
6455 +       dev->chunkShift = Shifts(x);
6456 +       x >>= dev->chunkShift;
6457 +       dev->chunkDiv = x;
6458 +       /* We only use chunk mask if chunkDiv is 1 */
6459 +       dev->chunkMask = (1<<dev->chunkShift) - 1;
6460 +               
6461         /*
6462          * Calculate chunkGroupBits.
6463          * We need to find the next power of 2 > than internalEndBlock
6464          */
6465  
6466         x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
6467 -
6468 +       
6469         bits = ShiftsGE(x);
6470 -
6471 +       
6472         /* Set up tnode width if wide tnodes are enabled. */
6473         if(!dev->wideTnodesDisabled){
6474                 /* bits must be even so that we end up with 32-bit words */
6475 @@ -7144,20 +7299,20 @@ int yaffs_GutsInitialise(yaffs_Device * 
6476         }
6477         else
6478                 dev->tnodeWidth = 16;
6479 -
6480
6481         dev->tnodeMask = (1<<dev->tnodeWidth)-1;
6482 -
6483 +               
6484         /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
6485          * so if the bitwidth of the
6486          * chunk range we're using is greater than 16 we need
6487          * to figure out chunk shift and chunkGroupSize
6488          */
6489 -
6490 +                
6491         if (bits <= dev->tnodeWidth)
6492                 dev->chunkGroupBits = 0;
6493         else
6494                 dev->chunkGroupBits = bits - dev->tnodeWidth;
6495 -
6496 +               
6497  
6498         dev->chunkGroupSize = 1 << dev->chunkGroupBits;
6499  
6500 @@ -7195,40 +7350,42 @@ int yaffs_GutsInitialise(yaffs_Device * 
6501         /* Initialise temporary buffers and caches. */
6502         if(!yaffs_InitialiseTempBuffers(dev))
6503                 init_failed = 1;
6504 -
6505 +       
6506         dev->srCache = NULL;
6507         dev->gcCleanupList = NULL;
6508 -
6509 -
6510 +       
6511 +       
6512         if (!init_failed &&
6513             dev->nShortOpCaches > 0) {
6514                 int i;
6515 -               __u8 *buf;
6516 +               void *buf;
6517                 int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
6518  
6519                 if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
6520                         dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
6521                 }
6522  
6523 -               buf = dev->srCache =  YMALLOC(srCacheBytes);
6524 -
6525 +               dev->srCache =  YMALLOC(srCacheBytes);
6526 +               
6527 +               buf = (__u8 *) dev->srCache;
6528 +                   
6529                 if(dev->srCache)
6530                         memset(dev->srCache,0,srCacheBytes);
6531 -
6532 +                  
6533                 for (i = 0; i < dev->nShortOpCaches && buf; i++) {
6534                         dev->srCache[i].object = NULL;
6535                         dev->srCache[i].lastUse = 0;
6536                         dev->srCache[i].dirty = 0;
6537 -                       dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
6538 +                       dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
6539                 }
6540                 if(!buf)
6541                         init_failed = 1;
6542 -
6543 +                       
6544                 dev->srLastUse = 0;
6545         }
6546  
6547         dev->cacheHits = 0;
6548 -
6549 +       
6550         if(!init_failed){
6551                 dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
6552                 if(!dev->gcCleanupList)
6553 @@ -7240,7 +7397,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
6554         }
6555         if(!init_failed && !yaffs_InitialiseBlocks(dev))
6556                 init_failed = 1;
6557 -
6558 +               
6559         yaffs_InitialiseTnodes(dev);
6560         yaffs_InitialiseObjects(dev);
6561  
6562 @@ -7252,18 +7409,19 @@ int yaffs_GutsInitialise(yaffs_Device * 
6563                 /* Now scan the flash. */
6564                 if (dev->isYaffs2) {
6565                         if(yaffs_CheckpointRestore(dev)) {
6566 +                               yaffs_CheckObjectDetailsLoaded(dev->rootDir);
6567                                 T(YAFFS_TRACE_ALWAYS,
6568                                   (TSTR("yaffs: restored from checkpoint" TENDSTR)));
6569                         } else {
6570  
6571 -                               /* Clean up the mess caused by an aborted checkpoint load
6572 -                                * and scan backwards.
6573 +                               /* Clean up the mess caused by an aborted checkpoint load 
6574 +                                * and scan backwards. 
6575                                  */
6576                                 yaffs_DeinitialiseBlocks(dev);
6577                                 yaffs_DeinitialiseTnodes(dev);
6578                                 yaffs_DeinitialiseObjects(dev);
6579 -
6580 -
6581 +                               
6582 +                       
6583                                 dev->nErasedBlocks = 0;
6584                                 dev->nFreeChunks = 0;
6585                                 dev->allocationBlock = -1;
6586 @@ -7275,7 +7433,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
6587  
6588                                 if(!init_failed && !yaffs_InitialiseBlocks(dev))
6589                                         init_failed = 1;
6590 -
6591 +                                       
6592                                 yaffs_InitialiseTnodes(dev);
6593                                 yaffs_InitialiseObjects(dev);
6594  
6595 @@ -7288,8 +7446,10 @@ int yaffs_GutsInitialise(yaffs_Device * 
6596                 }else
6597                         if(!yaffs_Scan(dev))
6598                                 init_failed = 1;
6599 -       }
6600  
6601 +               yaffs_StripDeletedObjects(dev);
6602 +       }
6603 +               
6604         if(init_failed){
6605                 /* Clean up the mess */
6606                 T(YAFFS_TRACE_TRACING,
6607 @@ -7310,7 +7470,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
6608  
6609         yaffs_VerifyFreeChunks(dev);
6610         yaffs_VerifyBlocks(dev);
6611 -
6612 +       
6613  
6614         T(YAFFS_TRACE_TRACING,
6615           (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
6616 @@ -7345,7 +7505,11 @@ void yaffs_Deinitialise(yaffs_Device * d
6617                         YFREE(dev->tempBuffer[i].buffer);
6618                 }
6619  
6620 +
6621                 dev->isMounted = 0;
6622 +               
6623 +               if(dev->deinitialiseNAND)
6624 +                       dev->deinitialiseNAND(dev);
6625         }
6626  
6627  }
6628 @@ -7394,7 +7558,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
6629  #endif
6630  
6631         nFree += dev->nDeletedFiles;
6632 -
6633 +       
6634         /* Now count the number of dirty chunks in the cache and subtract those */
6635  
6636         {
6637 @@ -7408,12 +7572,12 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
6638         nFree -= nDirtyCacheChunks;
6639  
6640         nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
6641 -
6642 +       
6643         /* Now we figure out how much to reserve for the checkpoint and report that... */
6644 -       blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
6645 +       blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
6646         if(blocksForCheckpoint < 0)
6647                 blocksForCheckpoint = 0;
6648 -
6649 +               
6650         nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
6651  
6652         if (nFree < 0)
6653 @@ -7429,10 +7593,10 @@ static void yaffs_VerifyFreeChunks(yaffs
6654  {
6655         int counted;
6656         int difference;
6657 -
6658 +       
6659         if(yaffs_SkipVerification(dev))
6660                 return;
6661 -
6662 +       
6663         counted = yaffs_CountFreeChunks(dev);
6664  
6665         difference = dev->nFreeChunks - counted;
6666 @@ -7448,22 +7612,25 @@ static void yaffs_VerifyFreeChunks(yaffs
6667  /*---------------------------------------- YAFFS test code ----------------------*/
6668  
6669  #define yaffs_CheckStruct(structure,syze, name) \
6670 +       do { \
6671             if(sizeof(structure) != syze) \
6672                { \
6673                  T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
6674                  name,syze,sizeof(structure))); \
6675                  return YAFFS_FAIL; \
6676 -               }
6677 +               } \
6678 +       } while(0)
6679  
6680  static int yaffs_CheckStructures(void)
6681  {
6682 -/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
6683 -/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
6684 -/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
6685 +/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */
6686 +/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */
6687 +/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */
6688  #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
6689 -       yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
6690 +        yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
6691 +#endif
6692 +#ifndef CONFIG_YAFFS_WINCE
6693 +               yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
6694  #endif
6695 -           yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
6696 -
6697             return YAFFS_OK;
6698  }
6699 --- a/fs/yaffs2/yaffs_mtdif1.c
6700 +++ b/fs/yaffs2/yaffs_mtdif1.c
6701 @@ -34,9 +34,9 @@
6702  #include "linux/mtd/mtd.h"
6703  
6704  /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
6705 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6706 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
6707  
6708 -const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $";
6709 +const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.8 2008-07-23 03:35:12 charles Exp $";
6710  
6711  #ifndef CONFIG_YAFFS_9BYTE_TAGS
6712  # define YTAG1_SIZE 8
6713 @@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
6714         ops.datbuf = data;
6715         ops.oobbuf = (__u8 *)&pt1;
6716  
6717 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
6718 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,20))
6719         /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
6720          * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
6721          */
6722 @@ -288,7 +288,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaf
6723         int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
6724         int retval;
6725  
6726 -       yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
6727 +       yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
6728  
6729         retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
6730         return (retval) ? YAFFS_FAIL : YAFFS_OK;
6731 @@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(stru
6732   * Always returns YAFFS_OK.
6733   */
6734  int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
6735 -       yaffs_BlockState * pState, int *pSequenceNumber)
6736 +       yaffs_BlockState * pState, __u32 *pSequenceNumber)
6737  {
6738         struct mtd_info * mtd = dev->genericDevice;
6739         int chunkNo = blockNo * dev->nChunksPerBlock;
6740 +       loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
6741         yaffs_ExtendedTags etags;
6742         int state = YAFFS_BLOCK_STATE_DEAD;
6743         int seqnum = 0;
6744 @@ -340,11 +341,16 @@ int nandmtd1_QueryNANDBlock(struct yaffs
6745         }
6746  
6747         retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
6748 +       etags.blockBad = (mtd->block_isbad)(mtd, addr);
6749         if (etags.blockBad) {
6750                 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
6751 -                       "block %d is marked bad", blockNo);
6752 +                       "block %d is marked bad\n", blockNo);
6753                 state = YAFFS_BLOCK_STATE_DEAD;
6754         }
6755 +       else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
6756 +               /* bad tags, need to look more closely */
6757 +               state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
6758 +       }
6759         else if (etags.chunkUsed) {
6760                 state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
6761                 seqnum = etags.sequenceNumber;
6762 @@ -360,4 +366,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs
6763         return YAFFS_OK;
6764  }
6765  
6766 -#endif /*KERNEL_VERSION*/
6767 +#endif /*MTD_VERSION*/
6768 --- a/fs/yaffs2/yaffs_mtdif2.c
6769 +++ b/fs/yaffs2/yaffs_mtdif2.c
6770 @@ -14,7 +14,7 @@
6771  /* mtd interface for YAFFS2 */
6772  
6773  const char *yaffs_mtdif2_c_version =
6774 -    "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $";
6775 +    "$Id: yaffs_mtdif2.c,v 1.22 2008-11-02 22:47:13 charles Exp $";
6776  
6777  #include "yportenv.h"
6778  
6779 @@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version =
6780  
6781  #include "yaffs_packedtags2.h"
6782  
6783 +/* NB For use with inband tags....
6784 + * We assume that the data buffer is of size totalBytersPerChunk so that we can also
6785 + * use it to load the tags.
6786 + */
6787  int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
6788                                       const __u8 * data,
6789                                       const yaffs_ExtendedTags * tags)
6790  {
6791         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
6792 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6793 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
6794         struct mtd_oob_ops ops;
6795  #else
6796         size_t dummy;
6797  #endif
6798         int retval = 0;
6799  
6800 -       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
6801 +       loff_t addr;
6802  
6803         yaffs_PackedTags2 pt;
6804  
6805 @@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
6806           (TSTR
6807            ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
6808             TENDSTR), chunkInNAND, data, tags));
6809 +           
6810  
6811 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6812 -       if (tags)
6813 -               yaffs_PackTags2(&pt, tags);
6814 +       addr  = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
6815 +       
6816 +       /* For yaffs2 writing there must be both data and tags.
6817 +        * If we're using inband tags, then the tags are stuffed into
6818 +        * the end of the data buffer.
6819 +        */
6820 +       if(!data || !tags)
6821 +               BUG();  
6822 +       else if(dev->inbandTags){
6823 +               yaffs_PackedTags2TagsPart *pt2tp;
6824 +               pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
6825 +               yaffs_PackTags2TagsPart(pt2tp,tags);
6826 +       }
6827         else
6828 -               BUG(); /* both tags and data should always be present */
6829 -
6830 -       if (data) {
6831 -               ops.mode = MTD_OOB_AUTO;
6832 -               ops.ooblen = sizeof(pt);
6833 -               ops.len = dev->nDataBytesPerChunk;
6834 -               ops.ooboffs = 0;
6835 -               ops.datbuf = (__u8 *)data;
6836 -               ops.oobbuf = (void *)&pt;
6837 -               retval = mtd->write_oob(mtd, addr, &ops);
6838 -       } else
6839 -               BUG(); /* both tags and data should always be present */
6840 -#else
6841 -       if (tags) {
6842                 yaffs_PackTags2(&pt, tags);
6843 -       }
6844 +       
6845 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6846 +       ops.mode = MTD_OOB_AUTO;
6847 +       ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
6848 +       ops.len = dev->totalBytesPerChunk;
6849 +       ops.ooboffs = 0;
6850 +       ops.datbuf = (__u8 *)data;
6851 +       ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
6852 +       retval = mtd->write_oob(mtd, addr, &ops);
6853  
6854 -       if (data && tags) {
6855 -               if (dev->useNANDECC)
6856 -                       retval =
6857 -                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
6858 -                                          &dummy, data, (__u8 *) & pt, NULL);
6859 -               else
6860 -                       retval =
6861 -                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
6862 -                                          &dummy, data, (__u8 *) & pt, NULL);
6863 +#else
6864 +       if (!dev->inbandTags) {
6865 +               retval =
6866 +                   mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
6867 +                                  &dummy, data, (__u8 *) & pt, NULL);
6868         } else {
6869 -               if (data)
6870 -                       retval =
6871 -                           mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
6872 -                                      data);
6873 -               if (tags)
6874 -                       retval =
6875 -                           mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
6876 -                                          (__u8 *) & pt);
6877 -
6878 +               retval =
6879 +                   mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
6880 +                              data);
6881         }
6882  #endif
6883  
6884 @@ -101,13 +100,14 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
6885                                        __u8 * data, yaffs_ExtendedTags * tags)
6886  {
6887         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
6888 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6889 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
6890         struct mtd_oob_ops ops;
6891  #endif
6892         size_t dummy;
6893         int retval = 0;
6894 +       int localData = 0;
6895  
6896 -       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
6897 +       loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
6898  
6899         yaffs_PackedTags2 pt;
6900  
6901 @@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
6902           (TSTR
6903            ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
6904             TENDSTR), chunkInNAND, data, tags));
6905 +           
6906 +       if(dev->inbandTags){
6907 +               
6908 +               if(!data) {
6909 +                       localData = 1;
6910 +                       data = yaffs_GetTempBuffer(dev,__LINE__);
6911 +               }
6912 +               
6913 +
6914 +       }
6915 +
6916  
6917  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6918 -       if (data && !tags)
6919 -               retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
6920 +       if (dev->inbandTags || (data && !tags))
6921 +               retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
6922                                 &dummy, data);
6923         else if (tags) {
6924                 ops.mode = MTD_OOB_AUTO;
6925 @@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
6926                 retval = mtd->read_oob(mtd, addr, &ops);
6927         }
6928  #else
6929 -       if (data && tags) {
6930 -               if (dev->useNANDECC) {
6931 -                       retval =
6932 -                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
6933 -                                         &dummy, data, dev->spareBuffer,
6934 -                                         NULL);
6935 -               } else {
6936 -                       retval =
6937 -                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
6938 +       if (!dev->inbandTags && data && tags) {
6939 +
6940 +               retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
6941                                           &dummy, data, dev->spareBuffer,
6942                                           NULL);
6943 -               }
6944         } else {
6945                 if (data)
6946                         retval =
6947                             mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
6948                                       data);
6949 -               if (tags)
6950 +               if (!dev->inbandTags && tags)
6951                         retval =
6952                             mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
6953                                           dev->spareBuffer);
6954         }
6955  #endif
6956  
6957 -       memcpy(&pt, dev->spareBuffer, sizeof(pt));
6958  
6959 -       if (tags)
6960 -               yaffs_UnpackTags2(tags, &pt);
6961 +       if(dev->inbandTags){
6962 +               if(tags){
6963 +                       yaffs_PackedTags2TagsPart * pt2tp;
6964 +                       pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];    
6965 +                       yaffs_UnpackTags2TagsPart(tags,pt2tp);
6966 +               }
6967 +       }
6968 +       else {
6969 +               if (tags){
6970 +                       memcpy(&pt, dev->spareBuffer, sizeof(pt));
6971 +                       yaffs_UnpackTags2(tags, &pt);
6972 +               }
6973 +       }
6974  
6975 +       if(localData)
6976 +               yaffs_ReleaseTempBuffer(dev,data,__LINE__);
6977 +       
6978         if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
6979 -               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
6980 -
6981 +               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;             
6982         if (retval == 0)
6983                 return YAFFS_OK;
6984         else
6985 @@ -178,7 +194,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
6986         retval =
6987             mtd->block_markbad(mtd,
6988                                blockNo * dev->nChunksPerBlock *
6989 -                              dev->nDataBytesPerChunk);
6990 +                              dev->totalBytesPerChunk);
6991  
6992         if (retval == 0)
6993                 return YAFFS_OK;
6994 @@ -188,7 +204,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
6995  }
6996  
6997  int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
6998 -                           yaffs_BlockState * state, int *sequenceNumber)
6999 +                           yaffs_BlockState * state, __u32 *sequenceNumber)
7000  {
7001         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7002         int retval;
7003 @@ -198,7 +214,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs
7004         retval =
7005             mtd->block_isbad(mtd,
7006                              blockNo * dev->nChunksPerBlock *
7007 -                            dev->nDataBytesPerChunk);
7008 +                            dev->totalBytesPerChunk);
7009  
7010         if (retval) {
7011                 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
7012 --- a/fs/yaffs2/yaffs_guts.h
7013 +++ b/fs/yaffs2/yaffs_guts.h
7014 @@ -1,5 +1,5 @@
7015  /*
7016 - * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
7017 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
7018   *
7019   * Copyright (C) 2002-2007 Aleph One Ltd.
7020   *   for Toby Churchill Ltd and Brightstar Engineering
7021 @@ -22,11 +22,11 @@
7022  #define YAFFS_OK       1
7023  #define YAFFS_FAIL  0
7024  
7025 -/* Give us a  Y=0x59,
7026 - * Give us an A=0x41,
7027 - * Give us an FF=0xFF
7028 +/* Give us a  Y=0x59, 
7029 + * Give us an A=0x41, 
7030 + * Give us an FF=0xFF 
7031   * Give us an S=0x53
7032 - * And what have we got...
7033 + * And what have we got... 
7034   */
7035  #define YAFFS_MAGIC                    0x5941FF53
7036  
7037 @@ -90,7 +90,7 @@
7038  
7039  #define YAFFS_MAX_SHORT_OP_CACHES      20
7040  
7041 -#define YAFFS_N_TEMP_BUFFERS           4
7042 +#define YAFFS_N_TEMP_BUFFERS           6
7043  
7044  /* We limit the number attempts at sucessfully saving a chunk of data.
7045   * Small-page devices have 32 pages per block; large-page devices have 64.
7046 @@ -102,7 +102,7 @@
7047   * The range is limited slightly to help distinguish bad numbers from good.
7048   * This also allows us to perhaps in the future use special numbers for
7049   * special purposes.
7050 - * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
7051 + * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, 
7052   * and is a larger number than the lifetime of a 2GB device.
7053   */
7054  #define YAFFS_LOWEST_SEQUENCE_NUMBER   0x00001000
7055 @@ -132,12 +132,12 @@ typedef struct {
7056  
7057  #ifndef CONFIG_YAFFS_NO_YAFFS1
7058  typedef struct {
7059 -       unsigned chunkId:20;
7060 -       unsigned serialNumber:2;
7061 -       unsigned byteCount:10;
7062 -       unsigned objectId:18;
7063 -       unsigned ecc:12;
7064 -       unsigned unusedStuff:2;
7065 +        unsigned chunkId:20;
7066 +        unsigned serialNumber:2;
7067 +        unsigned byteCountLSB:10;
7068 +        unsigned objectId:18;
7069 +        unsigned ecc:12;
7070 +        unsigned byteCountMSB:2;
7071  
7072  } yaffs_Tags;
7073  
7074 @@ -178,7 +178,7 @@ typedef struct {
7075  
7076         /* The following stuff only has meaning when we read */
7077         yaffs_ECCResult eccResult;
7078 -       unsigned blockBad;
7079 +       unsigned blockBad;      
7080  
7081         /* YAFFS 1 stuff */
7082         unsigned chunkDeleted;  /* The chunk is marked deleted */
7083 @@ -244,29 +244,29 @@ typedef enum {
7084         /* This block is empty */
7085  
7086         YAFFS_BLOCK_STATE_ALLOCATING,
7087 -       /* This block is partially allocated.
7088 +       /* This block is partially allocated. 
7089          * At least one page holds valid data.
7090          * This is the one currently being used for page
7091          * allocation. Should never be more than one of these
7092          */
7093  
7094 -       YAFFS_BLOCK_STATE_FULL,
7095 +       YAFFS_BLOCK_STATE_FULL, 
7096         /* All the pages in this block have been allocated.
7097          */
7098  
7099         YAFFS_BLOCK_STATE_DIRTY,
7100 -       /* All pages have been allocated and deleted.
7101 +       /* All pages have been allocated and deleted. 
7102          * Erase me, reuse me.
7103          */
7104  
7105 -       YAFFS_BLOCK_STATE_CHECKPOINT,
7106 +       YAFFS_BLOCK_STATE_CHECKPOINT,   
7107         /* This block is assigned to holding checkpoint data.
7108          */
7109  
7110 -       YAFFS_BLOCK_STATE_COLLECTING,
7111 +       YAFFS_BLOCK_STATE_COLLECTING,   
7112         /* This block is being garbage collected */
7113  
7114 -       YAFFS_BLOCK_STATE_DEAD
7115 +       YAFFS_BLOCK_STATE_DEAD  
7116         /* This block has failed and is not in use */
7117  } yaffs_BlockState;
7118  
7119 @@ -277,11 +277,11 @@ typedef struct {
7120  
7121         int softDeletions:10;   /* number of soft deleted pages */
7122         int pagesInUse:10;      /* number of pages in use */
7123 -       yaffs_BlockState blockState:4;  /* One of the above block states */
7124 +       unsigned blockState:4;  /* One of the above block states. NB use unsigned because enum is sometimes an int */
7125         __u32 needsRetiring:1;  /* Data has failed on this block, need to get valid data off */
7126                                 /* and retire the block. */
7127         __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
7128 -       __u32 gcPrioritise: 1;  /* An ECC check or blank check has failed on this block.
7129 +       __u32 gcPrioritise: 1;  /* An ECC check or blank check has failed on this block. 
7130                                    It should be prioritised for GC */
7131          __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
7132  
7133 @@ -300,11 +300,11 @@ typedef struct {
7134  
7135         /* Apply to everything  */
7136         int parentObjectId;
7137 -       __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
7138 -       YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
7139 +        __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
7140 +        YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
7141  
7142 -       /* Thes following apply to directories, files, symlinks - not hard links */
7143 -       __u32 yst_mode;         /* protection */
7144 +        /* The following apply to directories, files, symlinks - not hard links */
7145 +        __u32 yst_mode;         /* protection */
7146  
7147  #ifdef CONFIG_YAFFS_WINCE
7148         __u32 notForWinCE[5];
7149 @@ -331,11 +331,14 @@ typedef struct {
7150         __u32 win_ctime[2];
7151         __u32 win_atime[2];
7152         __u32 win_mtime[2];
7153 -       __u32 roomToGrow[4];
7154  #else
7155 -       __u32 roomToGrow[10];
7156 +       __u32 roomToGrow[6];
7157 +
7158  #endif
7159 +       __u32 inbandShadowsObject;
7160 +       __u32 inbandIsShrink;
7161  
7162 +       __u32 reservedSpace[2];
7163         int shadowsObject;      /* This object header shadows the specified object if > 0 */
7164  
7165         /* isShrink applies to object headers written when we shrink the file (ie resize) */
7166 @@ -381,7 +384,7 @@ typedef struct {
7167  } yaffs_FileStructure;
7168  
7169  typedef struct {
7170 -       struct list_head children;      /* list of child links */
7171 +        struct ylist_head children;     /* list of child links */
7172  } yaffs_DirectoryStructure;
7173  
7174  typedef struct {
7175 @@ -408,7 +411,7 @@ struct yaffs_ObjectStruct {
7176         __u8 renameAllowed:1;   /* Some objects are not allowed to be renamed. */
7177         __u8 unlinkAllowed:1;
7178         __u8 dirty:1;           /* the object needs to be written to flash */
7179 -       __u8 valid:1;           /* When the file system is being loaded up, this
7180 +       __u8 valid:1;           /* When the file system is being loaded up, this 
7181                                  * object might be created before the data
7182                                  * is available (ie. file data records appear before the header).
7183                                  */
7184 @@ -417,33 +420,36 @@ struct yaffs_ObjectStruct {
7185         __u8 deferedFree:1;     /* For Linux kernel. Object is removed from NAND, but is
7186                                  * still in the inode cache. Free of object is defered.
7187                                  * until the inode is released.
7188 -                                */
7189 +                                 */
7190 +        __u8 beingCreated:1;   /* This object is still being created so skip some checks. */
7191  
7192 -       __u8 serial;            /* serial number of chunk in NAND. Cached here */
7193 -       __u16 sum;              /* sum of the name to speed searching */
7194 +        __u8 serial;            /* serial number of chunk in NAND. Cached here */
7195 +/*        __u16 sum_prev; */
7196 +        __u16 sum;              /* sum of the name to speed searching */
7197 +/*        __u16 sum_trailer; */
7198  
7199 -       struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
7200 +        struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
7201  
7202 -       struct list_head hashLink;      /* list of objects in this hash bucket */
7203 +        struct ylist_head hashLink;     /* list of objects in this hash bucket */
7204  
7205 -       struct list_head hardLinks;     /* all the equivalent hard linked objects */
7206 +        struct ylist_head hardLinks;    /* all the equivalent hard linked objects */
7207  
7208 -       /* directory structure stuff */
7209 -       /* also used for linking up the free list */
7210 -       struct yaffs_ObjectStruct *parent;
7211 -       struct list_head siblings;
7212 +        /* directory structure stuff */
7213 +        /* also used for linking up the free list */
7214 +        struct yaffs_ObjectStruct *parent; 
7215 +        struct ylist_head siblings;
7216  
7217         /* Where's my object header in NAND? */
7218 -       int chunkId;
7219 +       int hdrChunk;
7220  
7221         int nDataChunks;        /* Number of data chunks attached to the file. */
7222  
7223         __u32 objectId;         /* the object id value */
7224  
7225 -       __u32 yst_mode;
7226 +        __u32 yst_mode;
7227  
7228  #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
7229 -       YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
7230 +        YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
7231  #endif
7232  
7233  #ifndef __KERNEL__
7234 @@ -485,31 +491,30 @@ struct yaffs_ObjectList_struct {
7235  typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
7236  
7237  typedef struct {
7238 -       struct list_head list;
7239 -       int count;
7240 +        struct ylist_head list;
7241 +        int count;
7242  } yaffs_ObjectBucket;
7243  
7244  
7245 -/* yaffs_CheckpointObject holds the definition of an object as dumped
7246 +/* yaffs_CheckpointObject holds the definition of an object as dumped 
7247   * by checkpointing.
7248   */
7249  
7250  typedef struct {
7251          int structType;
7252 -       __u32 objectId;
7253 +       __u32 objectId;         
7254         __u32 parentId;
7255 -       int chunkId;
7256 -
7257 +       int hdrChunk;
7258         yaffs_ObjectType variantType:3;
7259 -       __u8 deleted:1;
7260 -       __u8 softDeleted:1;
7261 -       __u8 unlinked:1;
7262 -       __u8 fake:1;
7263 +       __u8 deleted:1;         
7264 +       __u8 softDeleted:1;     
7265 +       __u8 unlinked:1;        
7266 +       __u8 fake:1;            
7267         __u8 renameAllowed:1;
7268         __u8 unlinkAllowed:1;
7269 -       __u8 serial;
7270 -
7271 -       int nDataChunks;
7272 +       __u8 serial;            
7273 +       
7274 +       int nDataChunks;        
7275         __u32 fileSizeOrEquivalentObjectId;
7276  
7277  }yaffs_CheckpointObject;
7278 @@ -528,25 +533,25 @@ typedef struct {
7279  /*----------------- Device ---------------------------------*/
7280  
7281  struct yaffs_DeviceStruct {
7282 -       struct list_head devList;
7283 -       const char *name;
7284 +        struct ylist_head devList;
7285 +        const char *name;
7286  
7287 -       /* Entry parameters set up way early. Yaffs sets up the rest.*/
7288 -       int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
7289 -       int nChunksPerBlock;    /* does not need to be a power of 2 */
7290 -       int nBytesPerSpare;     /* spare area size */
7291 -       int startBlock;         /* Start block we're allowed to use */
7292 -       int endBlock;           /* End block we're allowed to use */
7293 -       int nReservedBlocks;    /* We want this tuneable so that we can reduce */
7294 +        /* Entry parameters set up way early. Yaffs sets up the rest.*/
7295 +        int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
7296 +        int nChunksPerBlock;    /* does not need to be a power of 2 */
7297 +        int spareBytesPerChunk;/* spare area size */
7298 +        int startBlock;         /* Start block we're allowed to use */
7299 +        int endBlock;           /* End block we're allowed to use */
7300 +        int nReservedBlocks;    /* We want this tuneable so that we can reduce */
7301                                 /* reserved blocks on NOR and RAM. */
7302 -
7303 -
7304 +       
7305 +       
7306         /* Stuff used by the shared space checkpointing mechanism */
7307         /* If this value is zero, then this mechanism is disabled */
7308 +       
7309 +//     int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
7310  
7311 -       int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
7312 -
7313 -
7314 +       
7315  
7316  
7317         int nShortOpCaches;     /* If <= 0, then short op caching is disabled, else
7318 @@ -561,7 +566,7 @@ struct yaffs_DeviceStruct {
7319                                  * On an mtd this holds the mtd pointer.
7320                                  */
7321          void *superBlock;
7322 -
7323 +        
7324         /* NAND access functions (Must be set before calling YAFFS)*/
7325  
7326         int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
7327 @@ -570,12 +575,13 @@ struct yaffs_DeviceStruct {
7328         int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
7329                                   int chunkInNAND, __u8 * data,
7330                                   yaffs_Spare * spare);
7331 -       int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
7332 -                                int blockInNAND);
7333 -       int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
7334 +        int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
7335 +                                 int blockInNAND);
7336 +        int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
7337 +        int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev);
7338  
7339  #ifdef CONFIG_YAFFS_YAFFS2
7340 -       int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
7341 +        int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
7342                                          int chunkInNAND, const __u8 * data,
7343                                          const yaffs_ExtendedTags * tags);
7344         int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
7345 @@ -583,25 +589,27 @@ struct yaffs_DeviceStruct {
7346                                           yaffs_ExtendedTags * tags);
7347         int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
7348         int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
7349 -                              yaffs_BlockState * state, int *sequenceNumber);
7350 +                              yaffs_BlockState * state, __u32 *sequenceNumber);
7351  #endif
7352  
7353         int isYaffs2;
7354 -
7355 -       /* The removeObjectCallback function must be supplied by OS flavours that
7356 +       
7357 +       /* The removeObjectCallback function must be supplied by OS flavours that 
7358          * need it. The Linux kernel does not use this, but yaffs direct does use
7359          * it to implement the faster readdir
7360          */
7361         void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
7362 -
7363 +       
7364         /* Callback to mark the superblock dirsty */
7365         void (*markSuperBlockDirty)(void * superblock);
7366 -
7367 +       
7368         int wideTnodesDisabled; /* Set to disable wide tnodes */
7369 -
7370 +       
7371 +       YCHAR *pathDividers;    /* String of legal path dividers */
7372 +       
7373  
7374         /* End of stuff that must be set before initialisation. */
7375 -
7376 +       
7377         /* Checkpoint control. Can be set before or after initialisation */
7378         __u8 skipCheckpointRead;
7379         __u8 skipCheckpointWrite;
7380 @@ -610,34 +618,32 @@ struct yaffs_DeviceStruct {
7381  
7382         __u16 chunkGroupBits;   /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
7383         __u16 chunkGroupSize;   /* == 2^^chunkGroupBits */
7384 -
7385 +       
7386         /* Stuff to support wide tnodes */
7387         __u32 tnodeWidth;
7388         __u32 tnodeMask;
7389 -
7390 -       /* Stuff to support various file offses to chunk/offset translations */
7391 -       /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
7392 -       __u32 crumbMask;
7393 -       __u32 crumbShift;
7394 -       __u32 crumbsPerChunk;
7395 -
7396 -       /* Straight shifting for nDataBytesPerChunk being a power of 2 */
7397 -       __u32 chunkShift;
7398 -       __u32 chunkMask;
7399 -
7400 +       
7401 +       /* Stuff for figuring out file offset to chunk conversions */
7402 +       __u32 chunkShift; /* Shift value */
7403 +       __u32 chunkDiv;   /* Divisor after shifting: 1 for power-of-2 sizes */
7404 +       __u32 chunkMask;  /* Mask to use for power-of-2 case */
7405 +
7406 +       /* Stuff to handle inband tags */
7407 +       int inbandTags;
7408 +       __u32 totalBytesPerChunk;
7409  
7410  #ifdef __KERNEL__
7411  
7412         struct semaphore sem;   /* Semaphore for waiting on erasure.*/
7413         struct semaphore grossLock;     /* Gross locking semaphore */
7414 -       __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer
7415 +       __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer 
7416                                  * at compile time so we have to allocate it.
7417                                  */
7418         void (*putSuperFunc) (struct super_block * sb);
7419  #endif
7420  
7421         int isMounted;
7422 -
7423 +       
7424         int isCheckpointed;
7425  
7426  
7427 @@ -646,7 +652,7 @@ struct yaffs_DeviceStruct {
7428         int internalEndBlock;
7429         int blockOffset;
7430         int chunkOffset;
7431 -
7432 +       
7433  
7434         /* Runtime checkpointing stuff */
7435         int checkpointPageSequence;   /* running sequence number of checkpoint pages */
7436 @@ -662,13 +668,15 @@ struct yaffs_DeviceStruct {
7437         int checkpointMaxBlocks;
7438         __u32 checkpointSum;
7439         __u32 checkpointXor;
7440 -
7441 +       
7442 +       int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */
7443 +       
7444         /* Block Info */
7445         yaffs_BlockInfo *blockInfo;
7446         __u8 *chunkBits;        /* bitmap of chunks in use */
7447         unsigned blockInfoAlt:1;        /* was allocated using alternative strategy */
7448         unsigned chunkBitsAlt:1;        /* was allocated using alternative strategy */
7449 -       int chunkBitmapStride;  /* Number of bytes of chunkBits per block.
7450 +       int chunkBitmapStride;  /* Number of bytes of chunkBits per block. 
7451                                  * Must be consistent with nChunksPerBlock.
7452                                  */
7453  
7454 @@ -684,10 +692,14 @@ struct yaffs_DeviceStruct {
7455         yaffs_TnodeList *allocatedTnodeList;
7456  
7457         int isDoingGC;
7458 +       int gcBlock;
7459 +       int gcChunk;
7460  
7461         int nObjectsCreated;
7462         yaffs_Object *freeObjects;
7463         int nFreeObjects;
7464 +       
7465 +       int nHardLinks;
7466  
7467         yaffs_ObjectList *allocatedObjectList;
7468  
7469 @@ -716,7 +728,7 @@ struct yaffs_DeviceStruct {
7470         int tagsEccUnfixed;
7471         int nDeletions;
7472         int nUnmarkedDeletions;
7473 -
7474 +       
7475         int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
7476  
7477         /* Special directories */
7478 @@ -727,7 +739,7 @@ struct yaffs_DeviceStruct {
7479          *      __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
7480          *      yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
7481          */
7482 -
7483 +       
7484         int bufferedBlock;      /* Which block is buffered here? */
7485         int doingBufferedBlockRewrite;
7486  
7487 @@ -744,9 +756,11 @@ struct yaffs_DeviceStruct {
7488         int nUnlinkedFiles;             /* Count of unlinked files. */
7489         int nBackgroundDeletions;       /* Count of background deletions. */
7490  
7491 -
7492 +       
7493 +       /* Temporary buffer management */
7494         yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
7495         int maxTemp;
7496 +       int tempInUse;
7497         int unmanagedTempAllocations;
7498         int unmanagedTempDeallocations;
7499  
7500 @@ -758,17 +772,17 @@ struct yaffs_DeviceStruct {
7501  
7502  typedef struct yaffs_DeviceStruct yaffs_Device;
7503  
7504 -/* The static layout of bllock usage etc is stored in the super block header */
7505 +/* The static layout of block usage etc is stored in the super block header */
7506  typedef struct {
7507          int StructType;
7508 -       int version;
7509 +        int version;
7510         int checkpointStartBlock;
7511         int checkpointEndBlock;
7512         int startBlock;
7513         int endBlock;
7514         int rfu[100];
7515  } yaffs_SuperBlockHeader;
7516 -
7517 +       
7518  /* The CheckpointDevice structure holds the device information that changes at runtime and
7519   * must be preserved over unmount/mount cycles.
7520   */
7521 @@ -797,18 +811,6 @@ typedef struct {
7522      __u32 head;
7523  } yaffs_CheckpointValidity;
7524  
7525 -/* Function to manipulate block info */
7526 -static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
7527 -{
7528 -       if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
7529 -               T(YAFFS_TRACE_ERROR,
7530 -                 (TSTR
7531 -                  ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
7532 -                  blk));
7533 -               YBUG();
7534 -       }
7535 -       return &dev->blockInfo[blk - dev->internalStartBlock];
7536 -}
7537  
7538  /*----------------------- YAFFS Functions -----------------------*/
7539  
7540 @@ -834,13 +836,13 @@ int yaffs_GetAttributes(yaffs_Object * o
7541  
7542  /* File operations */
7543  int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
7544 -                          int nBytes);
7545 +                           int nBytes);
7546  int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
7547 -                         int nBytes, int writeThrough);
7548 +                          int nBytes, int writeThrough);
7549  int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
7550  
7551  yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
7552 -                             __u32 mode, __u32 uid, __u32 gid);
7553 +                              __u32 mode, __u32 uid, __u32 gid);
7554  int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
7555  
7556  /* Flushing and checkpointing */
7557 @@ -899,4 +901,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
7558  int yaffs_CheckFF(__u8 * buffer, int nBytes);
7559  void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
7560  
7561 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
7562 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo);
7563 +
7564  #endif
7565 --- a/fs/yaffs2/moduleconfig.h
7566 +++ b/fs/yaffs2/moduleconfig.h
7567 @@ -54,11 +54,11 @@ that you need to continue to support.  N
7568  older-style format.
7569  Note: Use of this option generally requires that MTD's oob layout be
7570  adjusted to use the older-style format.  See notes on tags formats and
7571 -MTD versions.
7572 +MTD versions in yaffs_mtdif1.c.
7573  */
7574  /* Default: Not selected */
7575  /* Meaning: Use older-style on-NAND data format with pageStatus byte */
7576 -#define CONFIG_YAFFS_9BYTE_TAGS
7577 +//#define CONFIG_YAFFS_9BYTE_TAGS
7578  
7579  #endif /* YAFFS_OUT_OF_TREE */
7580  
7581 --- a/fs/yaffs2/yaffs_mtdif1.h
7582 +++ b/fs/yaffs2/yaffs_mtdif1.h
7583 @@ -23,6 +23,6 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
7584  int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
7585  
7586  int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7587 -       yaffs_BlockState * state, int *sequenceNumber);
7588 +       yaffs_BlockState * state, __u32 *sequenceNumber);
7589  
7590  #endif
7591 --- a/fs/yaffs2/yaffs_mtdif2.h
7592 +++ b/fs/yaffs2/yaffs_mtdif2.h
7593 @@ -24,6 +24,6 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
7594                                        __u8 * data, yaffs_ExtendedTags * tags);
7595  int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
7596  int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7597 -                           yaffs_BlockState * state, int *sequenceNumber);
7598 +                           yaffs_BlockState * state, __u32 *sequenceNumber);
7599  
7600  #endif
7601 --- a/fs/yaffs2/yaffs_checkptrw.c
7602 +++ b/fs/yaffs2/yaffs_checkptrw.c
7603 @@ -12,11 +12,11 @@
7604   */
7605  
7606  const char *yaffs_checkptrw_c_version =
7607 -    "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $";
7608 +    "$Id: yaffs_checkptrw.c,v 1.17 2008-08-12 22:51:57 charles Exp $";
7609  
7610  
7611  #include "yaffs_checkptrw.h"
7612 -
7613 +#include "yaffs_getblockinfo.h"
7614  
7615  static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
7616  {
7617 @@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
7618                 return 0;
7619  
7620         if(!dev->checkpointBuffer)
7621 -               dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
7622 +               dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
7623         if(!dev->checkpointBuffer)
7624                 return 0;
7625  
7626 @@ -324,6 +324,7 @@ int yaffs_CheckpointRead(yaffs_Device *d
7627                                                               &tags);
7628  
7629                                 if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
7630 +                                  tags.eccResult > YAFFS_ECC_RESULT_FIXED ||
7631                                    tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
7632                                    ok = 0;
7633  
7634 --- a/fs/yaffs2/yaffs_tagscompat.c
7635 +++ b/fs/yaffs2/yaffs_tagscompat.c
7636 @@ -14,6 +14,7 @@
7637  #include "yaffs_guts.h"
7638  #include "yaffs_tagscompat.h"
7639  #include "yaffs_ecc.h"
7640 +#include "yaffs_getblockinfo.h"
7641  
7642  static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
7643  #ifdef NOTYET
7644 @@ -252,6 +253,9 @@ static int yaffs_ReadChunkFromNAND(struc
7645                 /* Must allocate enough memory for spare+2*sizeof(int) */
7646                 /* for ecc results from device. */
7647                 struct yaffs_NANDSpare nspare;
7648 +               
7649 +               memset(&nspare,0,sizeof(nspare));
7650 +               
7651                 retVal =
7652                     dev->readChunkFromNAND(dev, chunkInNAND, data,
7653                                            (yaffs_Spare *) & nspare);
7654 @@ -336,7 +340,7 @@ static void yaffs_HandleReadDataError(ya
7655         int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
7656  
7657         /* Mark the block for retirement */
7658 -       yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
7659 +       yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
7660         T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
7661           (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
7662  
7663 @@ -414,7 +418,16 @@ int yaffs_TagsCompatabilityWriteChunkWit
7664         } else {
7665                 tags.objectId = eTags->objectId;
7666                 tags.chunkId = eTags->chunkId;
7667 -               tags.byteCount = eTags->byteCount;
7668 +
7669 +               tags.byteCountLSB = eTags->byteCount & 0x3ff;
7670 +               
7671 +               if(dev->nDataBytesPerChunk >= 1024){
7672 +                       tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
7673 +               } else {
7674 +                       tags.byteCountMSB = 3;
7675 +               }
7676 +               
7677 +
7678                 tags.serialNumber = eTags->serialNumber;
7679  
7680                 if (!dev->useNANDECC && data) {
7681 @@ -435,10 +448,10 @@ int yaffs_TagsCompatabilityReadChunkWith
7682  
7683         yaffs_Spare spare;
7684         yaffs_Tags tags;
7685 -       yaffs_ECCResult eccResult;
7686 +       yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;
7687  
7688         static yaffs_Spare spareFF;
7689 -       static int init;
7690 +       static int init = 0;
7691  
7692         if (!init) {
7693                 memset(&spareFF, 0xFF, sizeof(spareFF));
7694 @@ -466,7 +479,11 @@ int yaffs_TagsCompatabilityReadChunkWith
7695  
7696                                 eTags->objectId = tags.objectId;
7697                                 eTags->chunkId = tags.chunkId;
7698 -                               eTags->byteCount = tags.byteCount;
7699 +                               eTags->byteCount = tags.byteCountLSB;
7700 +
7701 +                               if(dev->nDataBytesPerChunk >= 1024)
7702 +                                       eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
7703 +
7704                                 eTags->serialNumber = tags.serialNumber;
7705                         }
7706                 }
7707 @@ -497,9 +514,9 @@ int yaffs_TagsCompatabilityMarkNANDBlock
7708  }
7709  
7710  int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
7711 -                                         int blockNo, yaffs_BlockState *
7712 -                                         state,
7713 -                                         int *sequenceNumber)
7714 +                                         int blockNo,
7715 +                                         yaffs_BlockState *state,
7716 +                                         __u32 *sequenceNumber)
7717  {
7718  
7719         yaffs_Spare spare0, spare1;
7720 --- a/fs/yaffs2/yaffs_mtdif.c
7721 +++ b/fs/yaffs2/yaffs_mtdif.c
7722 @@ -12,7 +12,7 @@
7723   */
7724  
7725  const char *yaffs_mtdif_c_version =
7726 -    "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $";
7727 +    "$Id: yaffs_mtdif.c,v 1.21 2007-12-13 15:35:18 wookey Exp $";
7728  
7729  #include "yportenv.h"
7730  
7731 @@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version =
7732  #include "linux/time.h"
7733  #include "linux/mtd/nand.h"
7734  
7735 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
7736 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
7737  static struct nand_oobinfo yaffs_oobinfo = {
7738         .useecc = 1,
7739         .eccbytes = 6,
7740 @@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccin
7741  };
7742  #endif
7743  
7744 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7745 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7746  static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
7747  {
7748         oob[0] = spare->tagByte0;
7749 @@ -75,14 +75,14 @@ int nandmtd_WriteChunkToNAND(yaffs_Devic
7750                              const __u8 * data, const yaffs_Spare * spare)
7751  {
7752         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7753 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7754 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7755         struct mtd_oob_ops ops;
7756  #endif
7757         size_t dummy;
7758         int retval = 0;
7759  
7760         loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
7761 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7762 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7763         __u8 spareAsBytes[8]; /* OOB */
7764  
7765         if (data && !spare)
7766 @@ -139,14 +139,14 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi
7767                               yaffs_Spare * spare)
7768  {
7769         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7770 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7771 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7772         struct mtd_oob_ops ops;
7773  #endif
7774         size_t dummy;
7775         int retval = 0;
7776  
7777         loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
7778 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7779 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7780         __u8 spareAsBytes[8]; /* OOB */
7781  
7782         if (data && !spare)
7783 --- a/fs/yaffs2/yaffs_nandemul2k.h
7784 +++ b/fs/yaffs2/yaffs_nandemul2k.h
7785 @@ -22,13 +22,13 @@
7786  
7787  int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
7788                                         int chunkInNAND, const __u8 * data,
7789 -                                       yaffs_ExtendedTags * tags);
7790 +                                       const yaffs_ExtendedTags * tags);
7791  int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
7792                                          int chunkInNAND, __u8 * data,
7793                                          yaffs_ExtendedTags * tags);
7794  int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
7795  int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7796 -                             yaffs_BlockState * state, int *sequenceNumber);
7797 +                             yaffs_BlockState * state, __u32 *sequenceNumber);
7798  int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
7799                                 int blockInNAND);
7800  int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);