[kernel] generic-2.6/2.6.28: sync yaffs code with the current CVS version
authorGabor Juhos <juhosg@openwrt.org>
Fri, 23 Jan 2009 17:24:20 +0000 (17:24 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Fri, 23 Jan 2009 17:24:20 +0000 (17:24 +0000)
SVN-Revision: 14158

target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-01-23.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.28/512-yaffs_2.6.25_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.28/513-yaffs_2.6.26_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.28/514-yaffs_2.6.28_fixes.patch [deleted file]

diff --git a/target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-01-23.patch b/target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-01-23.patch
new file mode 100644 (file)
index 0000000..6193e89
--- /dev/null
@@ -0,0 +1,8237 @@
+--- a/fs/yaffs2/yaffs_tagscompat.h
++++ b/fs/yaffs2/yaffs_tagscompat.h
+@@ -30,8 +30,9 @@ int yaffs_TagsCompatabilityReadChunkWith
+ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
+                                           int blockNo);
+ int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
+-                                        int blockNo, yaffs_BlockState *
+-                                        state, int *sequenceNumber);
++                                        int blockNo, 
++                                        yaffs_BlockState *state,
++                                        __u32 *sequenceNumber);
+ void yaffs_CalcTagsECC(yaffs_Tags * tags);
+ int yaffs_CheckECCOnTags(yaffs_Tags * tags);
+--- a/fs/yaffs2/Kconfig
++++ b/fs/yaffs2/Kconfig
+@@ -43,7 +43,8 @@ config YAFFS_9BYTE_TAGS
+         format that you need to continue to support.  New data written
+         also uses the older-style format.  Note: Use of this option
+         generally requires that MTD's oob layout be adjusted to use the
+-        older-style format.  See notes on tags formats and MTD versions.
++        older-style format.  See notes on tags formats and MTD versions
++        in yaffs_mtdif1.c.
+         If unsure, say N.
+@@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD
+         If unsure, say N.
+-config YAFFS_CHECKPOINT_RESERVED_BLOCKS
+-      int "Reserved blocks for checkpointing"
+-      depends on YAFFS_YAFFS2
+-      default 10
+-      help
+-          Give the number of Blocks to reserve for checkpointing.
+-        Checkpointing saves the state at unmount so that mounting is
+-        much faster as a scan of all the flash to regenerate this state
+-        is not needed.  These Blocks are reserved per partition, so if
+-        you have very small partitions the default (10) may be a mess
+-        for you.  You can set this value to 0, but that does not mean
+-        checkpointing is disabled at all. There only won't be any
+-        specially reserved blocks for checkpointing, so if there is
+-        enough free space on the filesystem, it will be used for
+-        checkpointing.
+-
+-        If unsure, leave at default (10), but don't wonder if there are
+-        always 2MB used on your large page device partition (10 x 2k
+-        pagesize). When using small partitions or when being very small
+-        on space, you probably want to set this to zero.
+ config YAFFS_DISABLE_WIDE_TNODES
+       bool "Turn off wide tnodes"
+--- a/fs/yaffs2/yaffs_mtdif.h
++++ b/fs/yaffs2/yaffs_mtdif.h
+@@ -18,6 +18,11 @@
+ #include "yaffs_guts.h"
++#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
++extern struct nand_oobinfo yaffs_oobinfo;
++extern struct nand_oobinfo yaffs_noeccinfo;
++#endif
++
+ int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
+                            const __u8 * data, const yaffs_Spare * spare);
+ int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
+--- a/fs/yaffs2/devextras.h
++++ b/fs/yaffs2/devextras.h
+@@ -1,5 +1,5 @@
+ /*
+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
+  *
+  * Copyright (C) 2002-2007 Aleph One Ltd.
+  *   for Toby Churchill Ltd and Brightstar Engineering
+@@ -14,203 +14,145 @@
+  */
+ /*
+- * This file is just holds extra declarations used during development.
+- * Most of these are from kernel includes placed here so we can use them in
+- * applications.
++ * This file is just holds extra declarations of macros that would normally
++ * be providesd in the Linux kernel. These macros have been written from
++ * scratch but are functionally equivalent to the Linux ones.
+  *
+  */
+ #ifndef __EXTRAS_H__
+ #define __EXTRAS_H__
+-#if defined WIN32
+-#define __inline__ __inline
+-#define new newHack
+-#endif
+-
+-#if !(defined __KERNEL__) || (defined WIN32)
+-/* User space defines */
++#if !(defined __KERNEL__) 
++/* Definition of types */
+ typedef unsigned char __u8;
+ typedef unsigned short __u16;
+ typedef unsigned __u32;
++#endif
++
+ /*
+- * Simple doubly linked list implementation.
+- *
+- * Some of the internal functions ("__xxx") are useful when
+- * manipulating whole lists rather than single entries, as
+- * sometimes we already know the next/prev entries and we can
+- * generate better code by using them directly rather than
+- * using the generic single-entry routines.
++ * This is a simple doubly linked list implementation that matches the 
++ * way the Linux kernel doubly linked list implementation works.
+  */
+-#define prefetch(x) 1
+-
+-struct list_head {
+-      struct list_head *next, *prev;
++struct ylist_head {
++      struct ylist_head *next; /* next in chain */
++      struct ylist_head *prev; /* previous in chain */
+ };
+-#define LIST_HEAD_INIT(name) { &(name), &(name) }
+-#define LIST_HEAD(name) \
+-      struct list_head name = LIST_HEAD_INIT(name)
++/* Initialise a static list */
++#define YLIST_HEAD(name) \
++struct ylist_head name = { &(name),&(name)}
+-#define INIT_LIST_HEAD(ptr) do { \
+-      (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+-} while (0)
+-/*
+- * Insert a new entry between two known consecutive entries.
+- *
+- * This is only for internal list manipulation where we know
+- * the prev/next entries already!
+- */
+-static __inline__ void __list_add(struct list_head *new,
+-                                struct list_head *prev,
+-                                struct list_head *next)
+-{
+-      next->prev = new;
+-      new->next = next;
+-      new->prev = prev;
+-      prev->next = new;
+-}
+-/**
+- * list_add - add a new entry
+- * @new: new entry to be added
+- * @head: list head to add it after
+- *
+- * Insert a new entry after the specified head.
+- * This is good for implementing stacks.
+- */
+-static __inline__ void list_add(struct list_head *new, struct list_head *head)
+-{
+-      __list_add(new, head, head->next);
+-}
++/* Initialise a list head to an empty list */
++#define YINIT_LIST_HEAD(p) \
++do { \
++ (p)->next = (p);\
++ (p)->prev = (p); \
++} while(0)
+-/**
+- * list_add_tail - add a new entry
+- * @new: new entry to be added
+- * @head: list head to add it before
+- *
+- * Insert a new entry before the specified head.
+- * This is useful for implementing queues.
+- */
+-static __inline__ void list_add_tail(struct list_head *new,
+-                                   struct list_head *head)
++
++/* Add an element to a list */
++static __inline__ void ylist_add(struct ylist_head *newEntry, 
++                                 struct ylist_head *list)
+ {
+-      __list_add(new, head->prev, head);
++        struct ylist_head *listNext = list->next;
++        
++        list->next = newEntry;
++        newEntry->prev = list;
++      newEntry->next = listNext;
++      listNext->prev = newEntry;
++      
+ }
+-/*
+- * Delete a list entry by making the prev/next entries
+- * point to each other.
+- *
+- * This is only for internal list manipulation where we know
+- * the prev/next entries already!
+- */
+-static __inline__ void __list_del(struct list_head *prev,
+-                                struct list_head *next)
++static __inline__ void ylist_add_tail(struct ylist_head *newEntry, 
++                               struct ylist_head *list)
+ {
+-      next->prev = prev;
+-      prev->next = next;
++      struct ylist_head *listPrev = list->prev;
++      
++      list->prev = newEntry;
++      newEntry->next = list;
++      newEntry->prev = listPrev;
++      listPrev->next = newEntry;
++      
+ }
+-/**
+- * list_del - deletes entry from list.
+- * @entry: the element to delete from the list.
+- * Note: list_empty on entry does not return true after this, the entry is
+- * in an undefined state.
+- */
+-static __inline__ void list_del(struct list_head *entry)
++
++/* Take an element out of its current list, with or without
++ * reinitialising the links.of the entry*/
++static __inline__ void ylist_del(struct ylist_head *entry)
+ {
+-      __list_del(entry->prev, entry->next);
++        struct ylist_head *listNext = entry->next;
++        struct ylist_head *listPrev = entry->prev;
++        
++        listNext->prev = listPrev;
++        listPrev->next = listNext;
++        
+ }
+-/**
+- * list_del_init - deletes entry from list and reinitialize it.
+- * @entry: the element to delete from the list.
+- */
+-static __inline__ void list_del_init(struct list_head *entry)
++static __inline__ void ylist_del_init(struct ylist_head *entry)
+ {
+-      __list_del(entry->prev, entry->next);
+-      INIT_LIST_HEAD(entry);
++        ylist_del(entry);
++        entry->next = entry->prev = entry;
+ }
+-/**
+- * list_empty - tests whether a list is empty
+- * @head: the list to test.
+- */
+-static __inline__ int list_empty(struct list_head *head)
++
++/* Test if the list is empty */
++static __inline__ int ylist_empty(struct ylist_head *entry)
+ {
+-      return head->next == head;
++        return (entry->next == entry);
+ }
+-/**
+- * list_splice - join two lists
+- * @list: the new list to add.
+- * @head: the place to add it in the first list.
++
++/* ylist_entry takes a pointer to a list entry and offsets it to that
++ * we can find a pointer to the object it is embedded in.
+  */
+-static __inline__ void list_splice(struct list_head *list,
+-                                 struct list_head *head)
+-{
+-      struct list_head *first = list->next;
++ 
++ 
++#define ylist_entry(entry, type, member) \
++        ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
+-      if (first != list) {
+-              struct list_head *last = list->prev;
+-              struct list_head *at = head->next;
+-
+-              first->prev = head;
+-              head->next = first;
+-
+-              last->next = at;
+-              at->prev = last;
+-      }
+-}
+-/**
+- * list_entry - get the struct for this entry
+- * @ptr:      the &struct list_head pointer.
+- * @type:     the type of the struct this is embedded in.
+- * @member:   the name of the list_struct within the struct.
++/* ylist_for_each and list_for_each_safe  iterate over lists.
++ * ylist_for_each_safe uses temporary storage to make the list delete safe
+  */
+-#define list_entry(ptr, type, member) \
+-      ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+-/**
+- * list_for_each      -       iterate over a list
+- * @pos:      the &struct list_head to use as a loop counter.
+- * @head:     the head for your list.
+- */
+-#define list_for_each(pos, head) \
+-      for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+-              pos = pos->next, prefetch(pos->next))
+-
+-/**
+- * list_for_each_safe -       iterate over a list safe against removal
+- *                              of list entry
+- * @pos:      the &struct list_head to use as a loop counter.
+- * @n:                another &struct list_head to use as temporary storage
+- * @head:     the head for your list.
+- */
+-#define list_for_each_safe(pos, n, head) \
+-      for (pos = (head)->next, n = pos->next; pos != (head); \
+-              pos = n, n = pos->next)
++#define ylist_for_each(itervar, list) \
++        for (itervar = (list)->next; itervar != (list); itervar = itervar->next )
+-/*
+- * File types
+- */
+-#define DT_UNKNOWN    0
+-#define DT_FIFO               1
+-#define DT_CHR                2
++#define ylist_for_each_safe(itervar,saveVar, list) \
++        for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \
++         itervar = saveVar, saveVar = saveVar->next)
++
++
++#if !(defined __KERNEL__)
++
++
++#ifndef WIN32
++#include <sys/stat.h>
++#endif
++
++
++#ifdef CONFIG_YAFFS_PROVIDE_DEFS
++/* File types */
++
++
++#define DT_UNKNOWN      0
++#define DT_FIFO         1
++#define DT_CHR          2
+ #define DT_DIR                4
+ #define DT_BLK                6
+-#define DT_REG                8
+-#define DT_LNK                10
+-#define DT_SOCK               12
+-#define DT_WHT                14
++#define DT_REG          8
++#define DT_LNK          10
++#define DT_SOCK         12
++#define DT_WHT          14
++
+ #ifndef WIN32
+ #include <sys/stat.h>
+@@ -220,17 +162,13 @@ static __inline__ void list_splice(struc
+  * Attribute flags.  These should be or-ed together to figure out what
+  * has been changed!
+  */
+-#define ATTR_MODE     1
+-#define ATTR_UID      2
++#define ATTR_MODE       1
++#define ATTR_UID        2
+ #define ATTR_GID      4
+ #define ATTR_SIZE     8
+ #define ATTR_ATIME    16
+ #define ATTR_MTIME    32
+ #define ATTR_CTIME    64
+-#define ATTR_ATIME_SET        128
+-#define ATTR_MTIME_SET        256
+-#define ATTR_FORCE    512     /* Not a change, but a change it */
+-#define ATTR_ATTR_FLAG        1024
+ struct iattr {
+       unsigned int ia_valid;
+@@ -241,24 +179,21 @@ struct iattr {
+       unsigned ia_atime;
+       unsigned ia_mtime;
+       unsigned ia_ctime;
+-      unsigned int ia_attr_flags;
++        unsigned int ia_attr_flags;
+ };
++#endif
++
++
+ #define KERN_DEBUG
+ #else
+-#ifndef WIN32
+ #include <linux/types.h>
+-#include <linux/list.h>
+ #include <linux/fs.h>
+ #include <linux/stat.h>
+-#endif
+ #endif
+-#if defined WIN32
+-#undef new
+-#endif
+ #endif
+--- a/fs/yaffs2/yaffs_packedtags2.c
++++ b/fs/yaffs2/yaffs_packedtags2.c
+@@ -37,60 +37,70 @@
+ #define EXTRA_OBJECT_TYPE_SHIFT (28)
+ #define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
+-static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
++
++static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
+ {
+       T(YAFFS_TRACE_MTD,
+         (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
+-         pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
+-         pt->t.sequenceNumber));
++         ptt->objectId, ptt->chunkId, ptt->byteCount,
++         ptt->sequenceNumber));
++}
++static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
++{
++      yaffs_DumpPackedTags2TagsPart(&pt->t);
+ }
+ static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
+ {
+       T(YAFFS_TRACE_MTD,
+         (TSTR
+-         ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
+-          "%d del %d ser %d seq %d"
++         ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
+           TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
+          t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
+          t->sequenceNumber));
+ }
+-void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
++void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
+ {
+-      pt->t.chunkId = t->chunkId;
+-      pt->t.sequenceNumber = t->sequenceNumber;
+-      pt->t.byteCount = t->byteCount;
+-      pt->t.objectId = t->objectId;
++      ptt->chunkId = t->chunkId;
++      ptt->sequenceNumber = t->sequenceNumber;
++      ptt->byteCount = t->byteCount;
++      ptt->objectId = t->objectId;
+       if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
+               /* Store the extra header info instead */
+               /* We save the parent object in the chunkId */
+-              pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
++              ptt->chunkId = EXTRA_HEADER_INFO_FLAG
+                       | t->extraParentObjectId;
+               if (t->extraIsShrinkHeader) {
+-                      pt->t.chunkId |= EXTRA_SHRINK_FLAG;
++                      ptt->chunkId |= EXTRA_SHRINK_FLAG;
+               }
+               if (t->extraShadows) {
+-                      pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
++                      ptt->chunkId |= EXTRA_SHADOWS_FLAG;
+               }
+-              pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+-              pt->t.objectId |=
++              ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
++              ptt->objectId |=
+                   (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
+               if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
+-                      pt->t.byteCount = t->extraEquivalentObjectId;
++                      ptt->byteCount = t->extraEquivalentObjectId;
+               } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
+-                      pt->t.byteCount = t->extraFileLength;
++                      ptt->byteCount = t->extraFileLength;
+               } else {
+-                      pt->t.byteCount = 0;
++                      ptt->byteCount = 0;
+               }
+       }
+-      yaffs_DumpPackedTags2(pt);
++      yaffs_DumpPackedTags2TagsPart(ptt);
+       yaffs_DumpTags2(t);
++}
++
++
++void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
++{
++      yaffs_PackTags2TagsPart(&pt->t,t);
+ #ifndef YAFFS_IGNORE_TAGS_ECC
+       {
+@@ -101,20 +111,63 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
+ #endif
+ }
+-void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
++
++void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
+ {
+       memset(t, 0, sizeof(yaffs_ExtendedTags));
+       yaffs_InitialiseTags(t);
++      if (ptt->sequenceNumber != 0xFFFFFFFF) {
++              t->blockBad = 0;
++              t->chunkUsed = 1;
++              t->objectId = ptt->objectId;
++              t->chunkId = ptt->chunkId;
++              t->byteCount = ptt->byteCount;
++              t->chunkDeleted = 0;
++              t->serialNumber = 0;
++              t->sequenceNumber = ptt->sequenceNumber;
++
++              /* Do extra header info stuff */
++
++              if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
++                      t->chunkId = 0;
++                      t->byteCount = 0;
++
++                      t->extraHeaderInfoAvailable = 1;
++                      t->extraParentObjectId =
++                          ptt->chunkId & (~(ALL_EXTRA_FLAGS));
++                      t->extraIsShrinkHeader =
++                          (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
++                      t->extraShadows =
++                          (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
++                      t->extraObjectType =
++                          ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
++                      t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
++
++                      if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
++                              t->extraEquivalentObjectId = ptt->byteCount;
++                      } else {
++                              t->extraFileLength = ptt->byteCount;
++                      }
++              }
++      }
++
++      yaffs_DumpPackedTags2TagsPart(ptt);
++      yaffs_DumpTags2(t);
++
++}
++
++
++void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
++{
++
++      yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
++      
+       if (pt->t.sequenceNumber != 0xFFFFFFFF) {
+               /* Page is in use */
+-#ifdef YAFFS_IGNORE_TAGS_ECC
+-              {
+-                      t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+-              }
+-#else
++#ifndef YAFFS_IGNORE_TAGS_ECC
+               {
+                       yaffs_ECCOther ecc;
+                       int result;
+@@ -129,54 +182,27 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
+                                                 &pt->ecc, &ecc);
+                       switch(result){
+                               case 0:
+-                                      t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
++                                      eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+                                       break;
+                               case 1:
+-                                      t->eccResult = YAFFS_ECC_RESULT_FIXED;
++                                      eccResult = YAFFS_ECC_RESULT_FIXED;
+                                       break;
+                               case -1:
+-                                      t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
++                                      eccResult = YAFFS_ECC_RESULT_UNFIXED;
+                                       break;
+                               default:
+-                                      t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
++                                      eccResult = YAFFS_ECC_RESULT_UNKNOWN;
+                       }
+               }
+ #endif
+-              t->blockBad = 0;
+-              t->chunkUsed = 1;
+-              t->objectId = pt->t.objectId;
+-              t->chunkId = pt->t.chunkId;
+-              t->byteCount = pt->t.byteCount;
+-              t->chunkDeleted = 0;
+-              t->serialNumber = 0;
+-              t->sequenceNumber = pt->t.sequenceNumber;
+-
+-              /* Do extra header info stuff */
+-
+-              if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
+-                      t->chunkId = 0;
+-                      t->byteCount = 0;
+-
+-                      t->extraHeaderInfoAvailable = 1;
+-                      t->extraParentObjectId =
+-                          pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
+-                      t->extraIsShrinkHeader =
+-                          (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
+-                      t->extraShadows =
+-                          (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
+-                      t->extraObjectType =
+-                          pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
+-                      t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
+-
+-                      if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
+-                              t->extraEquivalentObjectId = pt->t.byteCount;
+-                      } else {
+-                              t->extraFileLength = pt->t.byteCount;
+-                      }
+-              }
+       }
++      yaffs_UnpackTags2TagsPart(t,&pt->t);
++      
++      t->eccResult = eccResult;
++
+       yaffs_DumpPackedTags2(pt);
+       yaffs_DumpTags2(t);
+ }
++
+--- a/fs/yaffs2/yaffs_ecc.c
++++ b/fs/yaffs2/yaffs_ecc.c
+@@ -29,7 +29,7 @@
+  */
+ const char *yaffs_ecc_c_version =
+-    "$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $";
++    "$Id: yaffs_ecc.c,v 1.10 2007-12-13 15:35:17 wookey Exp $";
+ #include "yportenv.h"
+--- a/fs/yaffs2/yaffs_packedtags2.h
++++ b/fs/yaffs2/yaffs_packedtags2.h
+@@ -33,6 +33,11 @@ typedef struct {
+       yaffs_ECCOther ecc;
+ } yaffs_PackedTags2;
++/* Full packed tags with ECC, used for oob tags */
+ void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
+ void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
++
++/* Only the tags part (no ECC for use with inband tags */
++void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * pt, const yaffs_ExtendedTags * t);
++void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * pt);
+ #endif
+--- a/fs/yaffs2/yportenv.h
++++ b/fs/yaffs2/yportenv.h
+@@ -17,6 +17,14 @@
+ #ifndef __YPORTENV_H__
+ #define __YPORTENV_H__
++/*
++ * Define the MTD version in terms of Linux Kernel versions
++ * This allows yaffs to be used independantly of the kernel
++ * as well as with it.
++ */
++
++#define MTD_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
++
+ #if defined CONFIG_YAFFS_WINCE
+ #include "ywinceenv.h"
+@@ -26,7 +34,10 @@
+ #include "moduleconfig.h"
+ /* Linux kernel */
++
+ #include <linux/version.h>
++#define MTD_VERSION_CODE LINUX_VERSION_CODE
++
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ #include <linux/config.h>
+ #endif
+@@ -40,6 +51,7 @@
+ #define YCHAR char
+ #define YUCHAR unsigned char
+ #define _Y(x)     x
++#define yaffs_strcat(a,b)    strcat(a,b)
+ #define yaffs_strcpy(a,b)    strcpy(a,b)
+ #define yaffs_strncpy(a,b,c) strncpy(a,b,c)
+ #define yaffs_strncmp(a,b,c) strncmp(a,b,c)
+@@ -90,6 +102,8 @@
+ #elif defined CONFIG_YAFFS_DIRECT
++#define MTD_VERSION_CODE MTD_VERSION(2,6,22)
++
+ /* Direct interface */
+ #include "ydirectenv.h"
+@@ -111,6 +125,7 @@
+ #define YCHAR char
+ #define YUCHAR unsigned char
+ #define _Y(x)     x
++#define yaffs_strcat(a,b)    strcat(a,b)
+ #define yaffs_strcpy(a,b)    strcpy(a,b)
+ #define yaffs_strncpy(a,b,c) strncpy(a,b,c)
+ #define yaffs_strlen(s)            strlen(s)
+@@ -180,8 +195,8 @@ extern unsigned int yaffs_wr_attempts;
+ #define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
+-#ifndef CONFIG_YAFFS_WINCE
+-#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
++#ifndef YBUG
++#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0)
+ #endif
+ #endif
+--- a/fs/yaffs2/Makefile
++++ b/fs/yaffs2/Makefile
+@@ -5,7 +5,6 @@
+ obj-$(CONFIG_YAFFS_FS) += yaffs.o
+ yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
+-yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
++yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
+ yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
+-yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o
+-yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o
++yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
+--- a/fs/yaffs2/yaffs_mtdif1-compat.c
++++ /dev/null
+@@ -1,434 +0,0 @@
+-From ian@brightstareng.com Fri May 18 15:06:49 2007
+-From ian@brightstareng.com Fri May 18 15:08:21 2007
+-Received: from 206.173.66.57.ptr.us.xo.net ([206.173.66.57] helo=zebra.brightstareng.com)
+-      by apollo.linkchoose.co.uk with esmtp (Exim 4.60)
+-      (envelope-from <ian@brightstareng.com>)
+-      id 1Hp380-00011e-T6
+-      for david.goodenough@linkchoose.co.uk; Fri, 18 May 2007 15:08:21 +0100
+-Received: from localhost (localhost.localdomain [127.0.0.1])
+-      by zebra.brightstareng.com (Postfix) with ESMTP
+-      id 4819F28C004; Fri, 18 May 2007 10:07:49 -0400 (EDT)
+-Received: from zebra.brightstareng.com ([127.0.0.1])
+- by localhost (zebra [127.0.0.1]) (amavisd-new, port 10024) with ESMTP
+- id 05328-06; Fri, 18 May 2007 10:07:16 -0400 (EDT)
+-Received: from pippin (unknown [192.168.1.25])
+-      by zebra.brightstareng.com (Postfix) with ESMTP
+-      id 8BEF528C1BC; Fri, 18 May 2007 10:06:53 -0400 (EDT)
+-From: Ian McDonnell <ian@brightstareng.com>
+-To: David Goodenough <david.goodenough@linkchoose.co.uk>
+-Subject: Re: something tested this time -- yaffs_mtdif1-compat.c
+-Date: Fri, 18 May 2007 10:06:49 -0400
+-User-Agent: KMail/1.9.1
+-References: <200705142207.06909.ian@brightstareng.com> <200705171131.53536.ian@brightstareng.com> <200705181334.32166.david.goodenough@linkchoose.co.uk>
+-In-Reply-To: <200705181334.32166.david.goodenough@linkchoose.co.uk>
+-Cc: Andrea Conti <alyf@alyf.net>,
+- Charles Manning <manningc2@actrix.gen.nz>
+-MIME-Version: 1.0
+-Content-Type: Multipart/Mixed;
+-  boundary="Boundary-00=_5LbTGmt62YoutxM"
+-Message-Id: <200705181006.49860.ian@brightstareng.com>
+-X-Virus-Scanned: by amavisd-new at brightstareng.com
+-Status: R
+-X-Status: NT
+-X-KMail-EncryptionState:
+-X-KMail-SignatureState:
+-X-KMail-MDN-Sent:
+-
+---Boundary-00=_5LbTGmt62YoutxM
+-Content-Type: text/plain;
+-  charset="iso-8859-15"
+-Content-Transfer-Encoding: 7bit
+-Content-Disposition: inline
+-
+-David, Andrea,
+-
+-On Friday 18 May 2007 08:34, you wrote:
+-> Yea team.  With this fix in place (I put it in the wrong place
+-> at first) I can now mount and ls the Yaffs partition without
+-> an error messages!
+-
+-Good news!
+-
+-Attached is a newer yaffs_mtdif1.c with a bandaid to help the
+-2.6.18 and 2.6.19 versions of MTD not trip on the oob read.
+-See the LINUX_VERSION_CODE conditional in
+-nandmtd1_ReadChunkWithTagsFromNAND.
+-
+--imcd
+-
+---Boundary-00=_5LbTGmt62YoutxM
+-Content-Type: text/x-csrc;
+-  charset="iso-8859-15";
+-  name="yaffs_mtdif1.c"
+-Content-Transfer-Encoding: 7bit
+-Content-Disposition: attachment;
+-      filename="yaffs_mtdif1.c"
+-
+-/*
+- * YAFFS: Yet another FFS. A NAND-flash specific file system.
+- * yaffs_mtdif1.c  NAND mtd interface functions for small-page NAND.
+- *
+- * Copyright (C) 2002 Aleph One Ltd.
+- *   for Toby Churchill Ltd and Brightstar Engineering
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-/*
+- * This module provides the interface between yaffs_nand.c and the
+- * MTD API.  This version is used when the MTD interface supports the
+- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
+- * and we have small-page NAND device.
+- *
+- * These functions are invoked via function pointers in yaffs_nand.c.
+- * This replaces functionality provided by functions in yaffs_mtdif.c
+- * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are
+- * called in yaffs_mtdif.c when the function pointers are NULL.
+- * We assume the MTD layer is performing ECC (useNANDECC is true).
+- */
+-
+-#include "yportenv.h"
+-#include "yaffs_guts.h"
+-#include "yaffs_packedtags1.h"
+-#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC
+-
+-#include "linux/kernel.h"
+-#include "linux/version.h"
+-#include "linux/types.h"
+-#include "linux/mtd/mtd.h"
+-
+-/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-
+-const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1-compat.c 13022 2008-10-22 06:51:06Z nbd $";
+-
+-#ifndef CONFIG_YAFFS_9BYTE_TAGS
+-# define YTAG1_SIZE 8
+-#else
+-# define YTAG1_SIZE 9
+-#endif
+-
+-#if 0
+-/* Use the following nand_ecclayout with MTD when using
+- * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout.
+- * If you have existing Yaffs images and the byte order differs from this,
+- * adjust 'oobfree' to match your existing Yaffs data.
+- *
+- * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the
+- * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to
+- * the 9th byte.
+- *
+- * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5
+- * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P
+- * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus
+- * byte and B is the small-page bad-block indicator byte.
+- */
+-static struct nand_ecclayout nand_oob_16 = {
+-      .eccbytes = 6,
+-      .eccpos = { 8, 9, 10, 13, 14, 15 },
+-      .oobavail = 9,
+-      .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
+-};
+-#endif
+-
+-/* Write a chunk (page) of data to NAND.
+- *
+- * Caller always provides ExtendedTags data which are converted to a more
+- * compact (packed) form for storage in NAND.  A mini-ECC runs over the
+- * contents of the tags meta-data; used to valid the tags when read.
+- *
+- *  - Pack ExtendedTags to PackedTags1 form
+- *  - Compute mini-ECC for PackedTags1
+- *  - Write data and packed tags to NAND.
+- *
+- * Note: Due to the use of the PackedTags1 meta-data which does not include
+- * a full sequence number (as found in the larger PackedTags2 form) it is
+- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
+- * discarded and dirty.  This is not ideal: newer NAND parts are supposed
+- * to be written just once.  When Yaffs performs this operation, this
+- * function is called with a NULL data pointer -- calling MTD write_oob
+- * without data is valid usage (2.6.17).
+- *
+- * Any underlying MTD error results in YAFFS_FAIL.
+- * Returns YAFFS_OK or YAFFS_FAIL.
+- */
+-int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
+-      int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags)
+-{
+-      struct mtd_info * mtd = dev->genericDevice;
+-      int chunkBytes = dev->nDataBytesPerChunk;
+-      loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
+-      struct mtd_oob_ops ops;
+-      yaffs_PackedTags1 pt1;
+-      int retval;
+-
+-      /* we assume that PackedTags1 and yaffs_Tags are compatible */
+-      compile_time_assertion(sizeof(yaffs_PackedTags1) == 12);
+-      compile_time_assertion(sizeof(yaffs_Tags) == 8);
+-
+-      yaffs_PackTags1(&pt1, etags);
+-      yaffs_CalcTagsECC((yaffs_Tags *)&pt1);
+-
+-      /* When deleting a chunk, the upper layer provides only skeletal
+-       * etags, one with chunkDeleted set.  However, we need to update the
+-       * tags, not erase them completely.  So we use the NAND write property
+-       * that only zeroed-bits stick and set tag bytes to all-ones and
+-       * zero just the (not) deleted bit.
+-       */
+-#ifndef CONFIG_YAFFS_9BYTE_TAGS
+-      if (etags->chunkDeleted) {
+-              memset(&pt1, 0xff, 8);
+-              /* clear delete status bit to indicate deleted */
+-              pt1.deleted = 0;
+-      }
+-#else
+-      ((__u8 *)&pt1)[8] = 0xff;
+-      if (etags->chunkDeleted) {
+-              memset(&pt1, 0xff, 8);
+-              /* zero pageStatus byte to indicate deleted */
+-              ((__u8 *)&pt1)[8] = 0;
+-      }
+-#endif
+-
+-      memset(&ops, 0, sizeof(ops));
+-      ops.mode = MTD_OOB_AUTO;
+-      ops.len = (data) ? chunkBytes : 0;
+-      ops.ooblen = YTAG1_SIZE;
+-      ops.datbuf = (__u8 *)data;
+-      ops.oobbuf = (__u8 *)&pt1;
+-
+-      retval = mtd->write_oob(mtd, addr, &ops);
+-      if (retval) {
+-              yaffs_trace(YAFFS_TRACE_MTD,
+-                      "write_oob failed, chunk %d, mtd error %d\n",
+-                      chunkInNAND, retval);
+-      }
+-      return retval ? YAFFS_FAIL : YAFFS_OK;
+-}
+-
+-/* Return with empty ExtendedTags but add eccResult.
+- */
+-static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval)
+-{
+-      if (etags) {
+-              memset(etags, 0, sizeof(*etags));
+-              etags->eccResult = eccResult;
+-      }
+-      return retval;
+-}
+-
+-/* Read a chunk (page) from NAND.
+- *
+- * Caller expects ExtendedTags data to be usable even on error; that is,
+- * all members except eccResult and blockBad are zeroed.
+- *
+- *  - Check ECC results for data (if applicable)
+- *  - Check for blank/erased block (return empty ExtendedTags if blank)
+- *  - Check the PackedTags1 mini-ECC (correct if necessary/possible)
+- *  - Convert PackedTags1 to ExtendedTags
+- *  - Update eccResult and blockBad members to refect state.
+- *
+- * Returns YAFFS_OK or YAFFS_FAIL.
+- */
+-int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
+-      int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags)
+-{
+-      struct mtd_info * mtd = dev->genericDevice;
+-      int chunkBytes = dev->nDataBytesPerChunk;
+-      loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
+-      int eccres = YAFFS_ECC_RESULT_NO_ERROR;
+-      struct mtd_oob_ops ops;
+-      yaffs_PackedTags1 pt1;
+-      int retval;
+-      int deleted;
+-
+-      memset(&ops, 0, sizeof(ops));
+-      ops.mode = MTD_OOB_AUTO;
+-      ops.len = (data) ? chunkBytes : 0;
+-      ops.ooblen = YTAG1_SIZE;
+-      ops.datbuf = data;
+-      ops.oobbuf = (__u8 *)&pt1;
+-
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+-      /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+-       * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+-       */
+-      ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+-#endif
+-      /* Read page and oob using MTD.
+-       * Check status and determine ECC result.
+-       */
+-      retval = mtd->read_oob(mtd, addr, &ops);
+-      if (retval) {
+-              yaffs_trace(YAFFS_TRACE_MTD,
+-                      "read_oob failed, chunk %d, mtd error %d\n",
+-                      chunkInNAND, retval);
+-      }
+-
+-      switch (retval) {
+-      case 0:
+-              /* no error */
+-              break;
+-
+-      case -EUCLEAN:
+-              /* MTD's ECC fixed the data */
+-              eccres = YAFFS_ECC_RESULT_FIXED;
+-              dev->eccFixed++;
+-              break;
+-
+-      case -EBADMSG:
+-              /* MTD's ECC could not fix the data */
+-              dev->eccUnfixed++;
+-              /* fall into... */
+-      default:
+-              rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
+-              etags->blockBad = (mtd->block_isbad)(mtd, addr);
+-              return YAFFS_FAIL;
+-      }
+-
+-      /* Check for a blank/erased chunk.
+-       */
+-      if (yaffs_CheckFF((__u8 *)&pt1, 8)) {
+-              /* when blank, upper layers want eccResult to be <= NO_ERROR */
+-              return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
+-      }
+-
+-#ifndef CONFIG_YAFFS_9BYTE_TAGS
+-      /* Read deleted status (bit) then return it to it's non-deleted
+-       * state before performing tags mini-ECC check. pt1.deleted is
+-       * inverted.
+-       */
+-      deleted = !pt1.deleted;
+-      pt1.deleted = 1;
+-#else
+-      (void) deleted; /* not used */
+-#endif
+-
+-      /* Check the packed tags mini-ECC and correct if necessary/possible.
+-       */
+-      retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1);
+-      switch (retval) {
+-      case 0:
+-              /* no tags error, use MTD result */
+-              break;
+-      case 1:
+-              /* recovered tags-ECC error */
+-              dev->tagsEccFixed++;
+-              eccres = YAFFS_ECC_RESULT_FIXED;
+-              break;
+-      default:
+-              /* unrecovered tags-ECC error */
+-              dev->tagsEccUnfixed++;
+-              return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
+-      }
+-
+-      /* Unpack the tags to extended form and set ECC result.
+-       * [set shouldBeFF just to keep yaffs_UnpackTags1 happy]
+-       */
+-      pt1.shouldBeFF = 0xFFFFFFFF;
+-      yaffs_UnpackTags1(etags, &pt1);
+-      etags->eccResult = eccres;
+-
+-      /* Set deleted state.
+-       */
+-#ifndef CONFIG_YAFFS_9BYTE_TAGS
+-      etags->chunkDeleted = deleted;
+-#else
+-      etags->chunkDeleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7);
+-#endif
+-      return YAFFS_OK;
+-}
+-
+-/* Mark a block bad.
+- *
+- * This is a persistant state.
+- * Use of this function should be rare.
+- *
+- * Returns YAFFS_OK or YAFFS_FAIL.
+- */
+-int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
+-{
+-      struct mtd_info * mtd = dev->genericDevice;
+-      int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
+-      int retval;
+-
+-      yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
+-
+-      retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
+-      return (retval) ? YAFFS_FAIL : YAFFS_OK;
+-}
+-
+-/* Check any MTD prerequists.
+- *
+- * Returns YAFFS_OK or YAFFS_FAIL.
+- */
+-static int nandmtd1_TestPrerequists(struct mtd_info * mtd)
+-{
+-      /* 2.6.18 has mtd->ecclayout->oobavail */
+-      /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
+-      int oobavail = mtd->ecclayout->oobavail;
+-
+-      if (oobavail < YTAG1_SIZE) {
+-              yaffs_trace(YAFFS_TRACE_ERROR,
+-                      "mtd device has only %d bytes for tags, need %d",
+-                      oobavail, YTAG1_SIZE);
+-              return YAFFS_FAIL;
+-      }
+-      return YAFFS_OK;
+-}
+-
+-/* Query for the current state of a specific block.
+- *
+- * Examine the tags of the first chunk of the block and return the state:
+- *  - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
+- *  - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use
+- *  - YAFFS_BLOCK_STATE_EMPTY, the block is clean
+- *
+- * Always returns YAFFS_OK.
+- */
+-int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+-      yaffs_BlockState * pState, int *pSequenceNumber)
+-{
+-      struct mtd_info * mtd = dev->genericDevice;
+-      int chunkNo = blockNo * dev->nChunksPerBlock;
+-      yaffs_ExtendedTags etags;
+-      int state = YAFFS_BLOCK_STATE_DEAD;
+-      int seqnum = 0;
+-      int retval;
+-
+-      /* We don't yet have a good place to test for MTD config prerequists.
+-       * Do it here as we are called during the initial scan.
+-       */
+-      if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) {
+-              return YAFFS_FAIL;
+-      }
+-
+-      retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
+-      if (etags.blockBad) {
+-              yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
+-                      "block %d is marked bad", blockNo);
+-              state = YAFFS_BLOCK_STATE_DEAD;
+-      }
+-      else if (etags.chunkUsed) {
+-              state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+-              seqnum = etags.sequenceNumber;
+-      }
+-      else {
+-              state = YAFFS_BLOCK_STATE_EMPTY;
+-      }
+-
+-      *pState = state;
+-      *pSequenceNumber = seqnum;
+-
+-      /* query always succeeds */
+-      return YAFFS_OK;
+-}
+-
+-#endif /*KERNEL_VERSION*/
+-
+---Boundary-00=_5LbTGmt62YoutxM--
+-
+-
+-
+--- a/fs/yaffs2/yaffs_fs.c
++++ b/fs/yaffs2/yaffs_fs.c
+@@ -32,7 +32,7 @@
+  */
+ const char *yaffs_fs_c_version =
+-    "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $";
++    "$Id: yaffs_fs.c,v 1.71 2009-01-22 00:45:54 charles Exp $";
+ extern const char *yaffs_guts_c_version;
+ #include <linux/version.h>
+@@ -43,7 +43,6 @@ extern const char *yaffs_guts_c_version;
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+-#include <linux/list.h>
+ #include <linux/fs.h>
+ #include <linux/proc_fs.h>
+ #include <linux/smp_lock.h>
+@@ -53,6 +52,8 @@ extern const char *yaffs_guts_c_version;
+ #include <linux/string.h>
+ #include <linux/ctype.h>
++#include "asm/div64.h"
++
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ #include <linux/statfs.h>     /* Added NCB 15-8-2003 */
+@@ -76,6 +77,12 @@ extern const char *yaffs_guts_c_version;
+ #endif
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
++#define YPROC_ROOT  &proc_root
++#else
++#define YPROC_ROOT  NULL
++#endif
++
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ #define WRITE_SIZE_STR "writesize"
+ #define WRITE_SIZE(mtd) (mtd)->writesize
+@@ -84,6 +91,13 @@ extern const char *yaffs_guts_c_version;
+ #define WRITE_SIZE(mtd) (mtd)->oobblock
+ #endif
++#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
++#define YAFFS_USE_WRITE_BEGIN_END 1
++#else
++#define YAFFS_USE_WRITE_BEGIN_END 0
++#endif
++
++
+ #include <asm/uaccess.h>
+ #include "yportenv.h"
+@@ -96,14 +110,30 @@ extern const char *yaffs_guts_c_version;
+ unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;
+ unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
++unsigned int yaffs_auto_checkpoint = 1;
+ /* Module Parameters */
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+ module_param(yaffs_traceMask,uint,0644);
+ module_param(yaffs_wr_attempts,uint,0644);
++module_param(yaffs_auto_checkpoint,uint,0644);
+ #else
+ MODULE_PARM(yaffs_traceMask,"i");
+ MODULE_PARM(yaffs_wr_attempts,"i");
++MODULE_PARM(yaffs_auto_checkpoint,"i");
++#endif
++
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
++/* use iget and read_inode */
++#define Y_IGET(sb,inum) iget((sb),(inum))
++static void yaffs_read_inode(struct inode *inode);
++
++#else
++/* Call local equivalent */
++#define YAFFS_USE_OWN_IGET
++#define Y_IGET(sb,inum) yaffs_iget((sb),(inum))
++
++static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino);
+ #endif
+ /*#define T(x) printk x */
+@@ -127,6 +157,8 @@ static void yaffs_put_super(struct super
+ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
+                               loff_t * pos);
++static ssize_t yaffs_hold_space(struct file *f);
++static void yaffs_release_space(struct file *f);
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ static int yaffs_file_flush(struct file *file, fl_owner_t id);
+@@ -181,9 +213,11 @@ static int yaffs_statfs(struct super_blo
+ #else
+ static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
+ #endif
+-static void yaffs_read_inode(struct inode *inode);
++#ifdef YAFFS_HAS_PUT_INODE
+ static void yaffs_put_inode(struct inode *inode);
++#endif
++
+ static void yaffs_delete_inode(struct inode *);
+ static void yaffs_clear_inode(struct inode *);
+@@ -193,10 +227,22 @@ static int yaffs_writepage(struct page *
+ #else
+ static int yaffs_writepage(struct page *page);
+ #endif
++
++
++#if (YAFFS_USE_WRITE_BEGIN_END != 0)
++static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
++                             loff_t pos, unsigned len, unsigned flags,
++                          struct page **pagep, void **fsdata);
++static int yaffs_write_end(struct file *filp, struct address_space *mapping,
++                         loff_t pos, unsigned len, unsigned copied,
++                         struct page *pg, void *fsdadata);
++#else
+ static int yaffs_prepare_write(struct file *f, struct page *pg,
+                              unsigned offset, unsigned to);
+ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
+                             unsigned to);
++                                                                                                
++#endif
+ static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
+                         int buflen);
+@@ -209,8 +255,13 @@ static int yaffs_follow_link(struct dent
+ static struct address_space_operations yaffs_file_address_operations = {
+       .readpage = yaffs_readpage,
+       .writepage = yaffs_writepage,
++#if (YAFFS_USE_WRITE_BEGIN_END > 0)
++      .write_begin = yaffs_write_begin,
++      .write_end = yaffs_write_end,
++#else
+       .prepare_write = yaffs_prepare_write,
+       .commit_write = yaffs_commit_write,
++#endif
+ };
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+@@ -224,6 +275,7 @@ static struct file_operations yaffs_file
+       .fsync = yaffs_sync_object,
+       .splice_read = generic_file_splice_read,
+       .splice_write = generic_file_splice_write,
++      .llseek = generic_file_llseek,
+ };
+ #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+@@ -284,8 +336,13 @@ static struct file_operations yaffs_dir_
+ static struct super_operations yaffs_super_ops = {
+       .statfs = yaffs_statfs,
++
++#ifndef YAFFS_USE_OWN_IGET
+       .read_inode = yaffs_read_inode,
++#endif
++#ifdef YAFFS_HAS_PUT_INODE
+       .put_inode = yaffs_put_inode,
++#endif
+       .put_super = yaffs_put_super,
+       .delete_inode = yaffs_delete_inode,
+       .clear_inode = yaffs_clear_inode,
+@@ -429,6 +486,9 @@ static struct dentry *yaffs_lookup(struc
+ }
++
++#ifdef YAFFS_HAS_PUT_INODE
++
+ /* For now put inode is just for debugging
+  * Put inode is called when the inode **structure** is put.
+  */
+@@ -439,6 +499,7 @@ static void yaffs_put_inode(struct inode
+          atomic_read(&inode->i_count)));
+ }
++#endif
+ /* clear is called to tell the fs to release any per-inode data it holds */
+ static void yaffs_clear_inode(struct inode *inode)
+@@ -667,6 +728,64 @@ static int yaffs_writepage(struct page *
+       return (nWritten == nBytes) ? 0 : -ENOSPC;
+ }
++
++#if (YAFFS_USE_WRITE_BEGIN_END > 0)
++static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
++                             loff_t pos, unsigned len, unsigned flags,
++                          struct page **pagep, void **fsdata)
++
++{
++      struct page *pg = NULL;
++        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
++        uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
++        uint32_t to = offset + len;
++        
++        int ret = 0;
++        int space_held = 0;
++        
++      T(YAFFS_TRACE_OS, (KERN_DEBUG "start yaffs_write_begin\n"));
++      /* Get a page */
++      pg = __grab_cache_page(mapping,index);
++      *pagep = pg;    
++      if(!pg){
++              ret =  -ENOMEM;
++              goto out;
++      }
++      /* Get fs space */
++      space_held = yaffs_hold_space(filp);
++      
++      if(!space_held){
++              ret = -ENOSPC;
++              goto out;
++      }
++              
++      /* Update page if required */
++      
++      if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
++              ret = yaffs_readpage_nolock(filp, pg);
++      
++      if(ret)
++              goto out;
++
++      /* Happy path return */
++      T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin - ok\n"));
++              
++      return 0;
++              
++out:
++      T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin fail returning %d\n",ret));
++      if(space_held){
++              yaffs_release_space(filp);
++      }
++      if(pg) {
++              unlock_page(pg);
++              page_cache_release(pg);
++      }
++      return ret;
++}
++
++#else
++
+ static int yaffs_prepare_write(struct file *f, struct page *pg,
+                              unsigned offset, unsigned to)
+ {
+@@ -674,22 +793,69 @@ static int yaffs_prepare_write(struct fi
+       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));
+       if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
+               return yaffs_readpage_nolock(f, pg);
+-
+       return 0;
+ }
++#endif
++
++#if (YAFFS_USE_WRITE_BEGIN_END > 0)
++static int yaffs_write_end(struct file *filp, struct address_space *mapping,
++                         loff_t pos, unsigned len, unsigned copied,
++                         struct page *pg, void *fsdadata)
++{
++      int ret = 0;
++      void *addr, *kva;
++        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
++        uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE -1); 
++
++
++      
++      kva=kmap(pg);
++      addr = kva + offset_into_page;
++
++      T(YAFFS_TRACE_OS,
++        (KERN_DEBUG "yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned) addr,
++         (int)pos, copied));
++
++      ret = yaffs_file_write(filp, addr, copied, &pos);
++
++      if (ret != copied) {
++              T(YAFFS_TRACE_OS,
++                (KERN_DEBUG
++                 "yaffs_write_end not same size ret %d  copied %d\n",
++                 ret, copied ));
++              SetPageError(pg);
++              ClearPageUptodate(pg);
++      } else {
++              SetPageUptodate(pg);
++      }
++
++      kunmap(pg);
++
++      yaffs_release_space(filp);
++      unlock_page(pg);
++      page_cache_release(pg);
++      return ret;
++}
++#else
+ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
+                             unsigned to)
+ {
+-      void *addr = page_address(pg) + offset;
++      void *addr, *kva;
++      
+       loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
+       int nBytes = to - offset;
+       int nWritten;
+       unsigned spos = pos;
+-      unsigned saddr = (unsigned)addr;
++      unsigned saddr;
++      
++      kva=kmap(pg);
++      addr = kva + offset;
++
++      saddr = (unsigned) addr;
+       T(YAFFS_TRACE_OS,
+         (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr,
+@@ -708,6 +874,8 @@ static int yaffs_commit_write(struct fil
+               SetPageUptodate(pg);
+       }
++      kunmap(pg);
++
+       T(YAFFS_TRACE_OS,
+         (KERN_DEBUG "yaffs_commit_write returning %d\n",
+          nWritten == nBytes ? 0 : nWritten));
+@@ -715,6 +883,8 @@ static int yaffs_commit_write(struct fil
+       return nWritten == nBytes ? 0 : nWritten;
+ }
++#endif
++
+ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
+ {
+@@ -753,6 +923,8 @@ static void yaffs_FillInodeFromObject(st
+                       break;
+               }
++              inode->i_flags |= S_NOATIME;
++              
+               inode->i_ino = obj->objectId;
+               inode->i_mode = obj->yst_mode;
+               inode->i_uid = obj->yst_uid;
+@@ -844,7 +1016,9 @@ struct inode *yaffs_get_inode(struct sup
+       T(YAFFS_TRACE_OS,
+         (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
+-      inode = iget(sb, obj->objectId);
++      inode = Y_IGET(sb, obj->objectId);
++      if(IS_ERR(inode))
++        return NULL;
+       /* NB Side effect: iget calls back to yaffs_read_inode(). */
+       /* iget also increments the inode's i_count */
+@@ -910,13 +1084,55 @@ static ssize_t yaffs_file_write(struct f
+       return nWritten == 0 ? -ENOSPC : nWritten;
+ }
++/* Space holding and freeing is done to ensure we have space available for write_begin/end */
++/* For now we just assume few parallel writes and check against a small number. */
++/* Todo: need to do this with a counter to handle parallel reads better */
++
++static ssize_t yaffs_hold_space(struct file *f)
++{
++      yaffs_Object *obj;
++      yaffs_Device *dev;
++      
++      int nFreeChunks;
++
++      
++      obj = yaffs_DentryToObject(f->f_dentry);
++
++      dev = obj->myDev;
++
++      yaffs_GrossLock(dev);
++
++      nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
++      
++      yaffs_GrossUnlock(dev);
++
++      return (nFreeChunks > 20) ? 1 : 0;
++}
++
++static void yaffs_release_space(struct file *f)
++{
++      yaffs_Object *obj;
++      yaffs_Device *dev;
++      
++      
++      obj = yaffs_DentryToObject(f->f_dentry);
++
++      dev = obj->myDev;
++
++      yaffs_GrossLock(dev);
++
++      
++      yaffs_GrossUnlock(dev);
++
++}
++
+ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
+ {
+       yaffs_Object *obj;
+       yaffs_Device *dev;
+       struct inode *inode = f->f_dentry->d_inode;
+       unsigned long offset, curoffs;
+-      struct list_head *i;
++      struct ylist_head *i;
+       yaffs_Object *l;
+       char name[YAFFS_MAX_NAME_LENGTH + 1];
+@@ -965,10 +1181,10 @@ static int yaffs_readdir(struct file *f,
+               f->f_version = inode->i_version;
+       }
+-      list_for_each(i, &obj->variant.directoryVariant.children) {
++      ylist_for_each(i, &obj->variant.directoryVariant.children) {
+               curoffs++;
+               if (curoffs >= offset) {
+-                      l = list_entry(i, yaffs_Object, siblings);
++                      l = ylist_entry(i, yaffs_Object, siblings);
+                       yaffs_GetObjectName(l, name,
+                                           YAFFS_MAX_NAME_LENGTH + 1);
+@@ -1269,7 +1485,7 @@ static int yaffs_rename(struct inode *ol
+       if (target &&
+           target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
+-          !list_empty(&target->variant.directoryVariant.children)) {
++          !ylist_empty(&target->variant.directoryVariant.children)) {
+               T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
+@@ -1350,25 +1566,47 @@ static int yaffs_statfs(struct super_blo
+       buf->f_type = YAFFS_MAGIC;
+       buf->f_bsize = sb->s_blocksize;
+       buf->f_namelen = 255;
+-      if (sb->s_blocksize > dev->nDataBytesPerChunk) {
+-
++      
++      if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
++              /* Do this if chunk size is not a power of 2 */
++              
++              uint64_t bytesInDev;
++              uint64_t bytesFree;
++
++              bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
++                           ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
++      
++              do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
++              buf->f_blocks = bytesInDev;
++
++              bytesFree  = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
++                           ((uint64_t)(dev->nDataBytesPerChunk));
++      
++              do_div(bytesFree,sb->s_blocksize);
++      
++              buf->f_bfree = bytesFree;
++      
++      } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
++      
+               buf->f_blocks =
+-                  (dev->endBlock - dev->startBlock +
+-                   1) * dev->nChunksPerBlock / (sb->s_blocksize /
+-                                                dev->nDataBytesPerChunk);
+-              buf->f_bfree =
+-                  yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
+-                                                      dev->nDataBytesPerChunk);
++                         (dev->endBlock - dev->startBlock + 1) * 
++                          dev->nChunksPerBlock / 
++                          (sb->s_blocksize / dev->nDataBytesPerChunk);
++              buf->f_bfree =
++                         yaffs_GetNumberOfFreeChunks(dev) / 
++                         (sb->s_blocksize / dev->nDataBytesPerChunk);
+       } else {
+-
+-              buf->f_blocks =
+-                  (dev->endBlock - dev->startBlock +
+-                   1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
+-                                                sb->s_blocksize);
+-              buf->f_bfree =
+-                  yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
+-                                                      sb->s_blocksize);
++             buf->f_blocks =
++                         (dev->endBlock - dev->startBlock + 1) * 
++                         dev->nChunksPerBlock * 
++                         (dev->nDataBytesPerChunk / sb->s_blocksize);
++                         
++                     buf->f_bfree =
++                         yaffs_GetNumberOfFreeChunks(dev) * 
++                         (dev->nDataBytesPerChunk / sb->s_blocksize);
+       }
++      
++      
+       buf->f_files = 0;
+       buf->f_ffree = 0;
+       buf->f_bavail = buf->f_bfree;
+@@ -1378,7 +1616,6 @@ static int yaffs_statfs(struct super_blo
+ }
+-/**
+ static int yaffs_do_sync_fs(struct super_block *sb)
+ {
+@@ -1388,8 +1625,10 @@ static int yaffs_do_sync_fs(struct super
+       if(sb->s_dirt) {
+               yaffs_GrossLock(dev);
+-              if(dev)
++              if(dev){
++                      yaffs_FlushEntireDeviceCache(dev);
+                       yaffs_CheckpointSave(dev);
++              }
+               yaffs_GrossUnlock(dev);
+@@ -1397,7 +1636,7 @@ static int yaffs_do_sync_fs(struct super
+       }
+       return 0;
+ }
+-**/
++
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+ static void yaffs_write_super(struct super_block *sb)
+@@ -1407,8 +1646,10 @@ static int yaffs_write_super(struct supe
+ {
+       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
++      if (yaffs_auto_checkpoint >= 2)
++              yaffs_do_sync_fs(sb);
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
+-      return 0; /* yaffs_do_sync_fs(sb);*/
++      return 0; 
+ #endif
+ }
+@@ -1422,10 +1663,48 @@ static int yaffs_sync_fs(struct super_bl
+       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
+-      return 0; /* yaffs_do_sync_fs(sb);*/
++      if (yaffs_auto_checkpoint >= 1)
++              yaffs_do_sync_fs(sb);
++      
++      return 0; 
+ }
++#ifdef YAFFS_USE_OWN_IGET
++
++static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino)
++{
++      struct inode *inode;
++      yaffs_Object *obj;
++      yaffs_Device *dev = yaffs_SuperToDevice(sb);
++
++      T(YAFFS_TRACE_OS,
++        (KERN_DEBUG "yaffs_iget for %lu\n", ino));
++
++      inode = iget_locked(sb, ino);
++      if (!inode)
++              return ERR_PTR(-ENOMEM);
++      if (!(inode->i_state & I_NEW))
++              return inode;
++
++       /* NB This is called as a side effect of other functions, but
++      * we had to release the lock to prevent deadlocks, so
++      * need to lock again.
++      */
++    
++      yaffs_GrossLock(dev);
++
++      obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
++
++      yaffs_FillInodeFromObject(inode, obj);
++
++      yaffs_GrossUnlock(dev);
++      
++      unlock_new_inode(inode);
++      return inode;
++}
++
++#else
+ static void yaffs_read_inode(struct inode *inode)
+ {
+@@ -1449,7 +1728,9 @@ static void yaffs_read_inode(struct inod
+       yaffs_GrossUnlock(dev);
+ }
+-static LIST_HEAD(yaffs_dev_list);
++#endif
++
++static YLIST_HEAD(yaffs_dev_list);
+ #if 0 // not used
+ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
+@@ -1503,7 +1784,7 @@ static void yaffs_put_super(struct super
+       yaffs_GrossUnlock(dev);
+       /* we assume this is protected by lock_kernel() in mount/umount */
+-      list_del(&dev->devList);
++      ylist_del(&dev->devList);
+       if(dev->spareBuffer){
+               YFREE(dev->spareBuffer);
+@@ -1532,8 +1813,8 @@ static void yaffs_MarkSuperBlockDirty(vo
+       struct super_block *sb = (struct super_block *)vsb;
+       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb));
+-//    if(sb)
+-//            sb->s_dirt = 1;
++      if(sb)
++              sb->s_dirt = 1;
+ }
+ typedef struct {
+@@ -1602,6 +1883,7 @@ static struct super_block *yaffs_interna
+       sb->s_magic = YAFFS_MAGIC;
+       sb->s_op = &yaffs_super_ops;
++      sb->s_flags |= MS_NOATIME;
+       if (!sb)
+               printk(KERN_INFO "yaffs: sb is NULL\n");
+@@ -1678,22 +1960,15 @@ static struct super_block *yaffs_interna
+ #ifdef CONFIG_YAFFS_AUTO_YAFFS2
+       if (yaffsVersion == 1 &&
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-          mtd->writesize >= 2048) {
+-#else
+-          mtd->oobblock >= 2048) {
+-#endif
++          WRITE_SIZE(mtd) >= 2048) {
+           T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
+           yaffsVersion = 2;
+       }
+       /* Added NCB 26/5/2006 for completeness */
+-      if (yaffsVersion == 2 &&
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-          mtd->writesize == 512) {
+-#else
+-          mtd->oobblock == 512) {
+-#endif
++      if (yaffsVersion == 2 && 
++          !options.inband_tags &&
++          WRITE_SIZE(mtd) == 512){
+           T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
+           yaffsVersion = 1;
+       }
+@@ -1719,12 +1994,9 @@ static struct super_block *yaffs_interna
+                       return NULL;
+               }
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-              if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+-#else
+-              if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+-#endif
+-                  mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
++              if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
++                  mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
++                  !options.inband_tags) {
+                       T(YAFFS_TRACE_ALWAYS,
+                         ("yaffs: MTD device does not have the "
+                          "right page sizes\n"));
+@@ -1784,9 +2056,10 @@ static struct super_block *yaffs_interna
+       dev->startBlock = 0;
+       dev->endBlock = nBlocks - 1;
+       dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
+-      dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
++      dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
+       dev->nReservedBlocks = 5;
+       dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
++      dev->inbandTags = options.inband_tags;
+       /* ... and the functions. */
+       if (yaffsVersion == 2) {
+@@ -1799,15 +2072,14 @@ static struct super_block *yaffs_interna
+               dev->spareBuffer = YMALLOC(mtd->oobsize);
+               dev->isYaffs2 = 1;
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-              dev->nDataBytesPerChunk = mtd->writesize;
++              dev->totalBytesPerChunk = mtd->writesize;
+               dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
+ #else
+-              dev->nDataBytesPerChunk = mtd->oobblock;
++              dev->totalBytesPerChunk = mtd->oobblock;
+               dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
+ #endif
+               nBlocks = mtd->size / mtd->erasesize;
+-              dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;
+               dev->startBlock = 0;
+               dev->endBlock = nBlocks - 1;
+       } else {
+@@ -1847,7 +2119,7 @@ static struct super_block *yaffs_interna
+       dev->skipCheckpointWrite = options.skip_checkpoint_write;
+       /* we assume this is protected by lock_kernel() in mount/umount */
+-      list_add_tail(&dev->devList, &yaffs_dev_list);
++      ylist_add_tail(&dev->devList, &yaffs_dev_list);
+       init_MUTEX(&dev->grossLock);
+@@ -1884,6 +2156,9 @@ static struct super_block *yaffs_interna
+               return NULL;
+       }
+       sb->s_root = root;
++      sb->s_dirt = !dev->isCheckpointed;
++      T(YAFFS_TRACE_ALWAYS,
++        ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));
+       T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
+       return sb;
+@@ -1990,12 +2265,12 @@ static char *yaffs_dump_dev(char *buf, y
+ {
+       buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
+       buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
++      buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);
+       buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);
+       buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
+       buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
+       buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
+       buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks);
+-      buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks);
+       buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);
+       buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
+       buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
+@@ -2006,10 +2281,8 @@ static char *yaffs_dump_dev(char *buf, y
+       buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
+       buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
+       buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
+-      buf +=
+-          sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
+-      buf +=
+-          sprintf(buf, "passiveGCs......... %d\n",
++      buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
++      buf += sprintf(buf, "passiveGCs......... %d\n",
+                   dev->passiveGarbageCollections);
+       buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
+       buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches);
+@@ -2025,6 +2298,7 @@ static char *yaffs_dump_dev(char *buf, y
+           sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
+       buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
+       buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
++      buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
+       return buf;
+ }
+@@ -2033,7 +2307,7 @@ static int yaffs_proc_read(char *page,
+                          char **start,
+                          off_t offset, int count, int *eof, void *data)
+ {
+-      struct list_head *item;
++      struct ylist_head *item;
+       char *buf = page;
+       int step = offset;
+       int n = 0;
+@@ -2057,8 +2331,8 @@ static int yaffs_proc_read(char *page,
+       lock_kernel();
+       /* Locate and print the Nth entry.  Order N-squared but N is small. */
+-      list_for_each(item, &yaffs_dev_list) {
+-              yaffs_Device *dev = list_entry(item, yaffs_Device, devList);
++      ylist_for_each(item, &yaffs_dev_list) {
++              yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList);
+               if (n < step) {
+                       n++;
+                       continue;
+@@ -2231,7 +2505,7 @@ static int __init init_yaffs_fs(void)
+       /* Install the proc_fs entry */
+       my_proc_entry = create_proc_entry("yaffs",
+                                              S_IRUGO | S_IFREG,
+-                                             &proc_root);
++                                             YPROC_ROOT);
+       if (my_proc_entry) {
+               my_proc_entry->write_proc = yaffs_proc_write;
+@@ -2277,7 +2551,7 @@ static void __exit exit_yaffs_fs(void)
+       T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__
+                              " removing. \n"));
+-      remove_proc_entry("yaffs", &proc_root);
++      remove_proc_entry("yaffs", YPROC_ROOT);
+       fsinst = fs_to_install;
+--- /dev/null
++++ b/fs/yaffs2/yaffs_getblockinfo.h
+@@ -0,0 +1,34 @@
++/*
++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
++ *
++ * Copyright (C) 2002-2007 Aleph One Ltd.
++ *   for Toby Churchill Ltd and Brightstar Engineering
++ *
++ * Created by Charles Manning <charles@aleph1.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 2.1 as
++ * published by the Free Software Foundation.
++ *
++ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
++ */
++
++#ifndef __YAFFS_GETBLOCKINFO_H__
++#define __YAFFS_GETBLOCKINFO_H__
++
++#include "yaffs_guts.h"
++
++/* Function to manipulate block info */
++static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
++{
++      if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
++              T(YAFFS_TRACE_ERROR,
++                (TSTR
++                 ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
++                 blk));
++              YBUG();
++      }
++      return &dev->blockInfo[blk - dev->internalStartBlock];
++}
++
++#endif
+--- a/fs/yaffs2/yaffs_nand.c
++++ b/fs/yaffs2/yaffs_nand.c
+@@ -12,12 +12,13 @@
+  */
+ const char *yaffs_nand_c_version =
+-    "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $";
++    "$Id: yaffs_nand.c,v 1.9 2008-05-05 07:58:58 charles Exp $";
+ #include "yaffs_nand.h"
+ #include "yaffs_tagscompat.h"
+ #include "yaffs_tagsvalidity.h"
++#include "yaffs_getblockinfo.h"
+ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
+                                          __u8 * buffer,
+@@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * de
+ int yaffs_QueryInitialBlockState(yaffs_Device * dev,
+                                                int blockNo,
+                                                yaffs_BlockState * state,
+-                                               unsigned *sequenceNumber)
++                                               __u32 *sequenceNumber)
+ {
+       blockNo -= dev->blockOffset;
+--- a/fs/yaffs2/yaffs_guts.c
++++ b/fs/yaffs2/yaffs_guts.c
+@@ -11,14 +11,16 @@
+  * published by the Free Software Foundation.
+  */
++
+ const char *yaffs_guts_c_version =
+-    "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $";
++    "$Id: yaffs_guts.c,v 1.76 2009-01-23 06:36:49 charles Exp $";
+ #include "yportenv.h"
+ #include "yaffsinterface.h"
+ #include "yaffs_guts.h"
+ #include "yaffs_tagsvalidity.h"
++#include "yaffs_getblockinfo.h"
+ #include "yaffs_tagscompat.h"
+ #ifndef  CONFIG_YAFFS_USE_OWN_SORT
+@@ -32,11 +34,6 @@ const char *yaffs_guts_c_version =
+ #include "yaffs_packedtags2.h"
+-#ifdef CONFIG_YAFFS_WINCE
+-void yfsd_LockYAFFS(BOOL fsLockOnly);
+-void yfsd_UnlockYAFFS(BOOL fsLockOnly);
+-#endif
+-
+ #define YAFFS_PASSIVE_GC_CHUNKS 2
+ #include "yaffs_ecc.h"
+@@ -78,9 +75,6 @@ static int yaffs_DoGenericObjectDeletion
+ static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
+-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
+-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+-                                  int lineNo);
+ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
+                                 int chunkInNAND);
+@@ -99,6 +93,7 @@ static void yaffs_VerifyFreeChunks(yaffs
+ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
++static void yaffs_VerifyDirectory(yaffs_Object *directory);
+ #ifdef YAFFS_PARANOID
+ static int yaffs_CheckFileSanity(yaffs_Object * in);
+ #else
+@@ -121,95 +116,109 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
+ /* Function to calculate chunk and offset */
+-static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
++static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
+ {
+-      if(dev->chunkShift){
+-              /* Easy-peasy power of 2 case */
+-              *chunk  = (__u32)(addr >> dev->chunkShift);
+-              *offset = (__u32)(addr & dev->chunkMask);
+-      }
+-      else if(dev->crumbsPerChunk)
++      int chunk;
++      __u32 offset;
++      
++      chunk  = (__u32)(addr >> dev->chunkShift);
++              
++      if(dev->chunkDiv == 1)
+       {
+-              /* Case where we're using "crumbs" */
+-              *offset = (__u32)(addr & dev->crumbMask);
+-              addr >>= dev->crumbShift;
+-              *chunk = ((__u32)addr)/dev->crumbsPerChunk;
+-              *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
++              /* easy power of 2 case */
++              offset = (__u32)(addr & dev->chunkMask);
+       }
+       else
+-              YBUG();
++      {
++              /* Non power-of-2 case */
++              
++              loff_t chunkBase;
++              
++              chunk /= dev->chunkDiv;
++              
++              chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
++              offset = (__u32)(addr - chunkBase);
++      }
++
++      *chunkOut = chunk;
++      *offsetOut = offset;
+ }
+-/* Function to return the number of shifts for a power of 2 greater than or equal
++/* Function to return the number of shifts for a power of 2 greater than or equal 
+  * to the given number
+  * Note we don't try to cater for all possible numbers and this does not have to
+  * be hellishly efficient.
+  */
+-
++ 
+ static __u32 ShiftsGE(__u32 x)
+ {
+       int extraBits;
+       int nShifts;
+-
++      
+       nShifts = extraBits = 0;
+-
++      
+       while(x>1){
+               if(x & 1) extraBits++;
+               x>>=1;
+               nShifts++;
+       }
+-      if(extraBits)
++      if(extraBits) 
+               nShifts++;
+-
++              
+       return nShifts;
+ }
+ /* Function to return the number of shifts to get a 1 in bit 0
+  */
+-
+-static __u32 ShiftDiv(__u32 x)
++ 
++static __u32 Shifts(__u32 x)
+ {
+       int nShifts;
+-
++      
+       nShifts =  0;
+-
++      
+       if(!x) return 0;
+-
++      
+       while( !(x&1)){
+               x>>=1;
+               nShifts++;
+       }
+-
++              
+       return nShifts;
+ }
+-/*
++/* 
+  * Temporary buffer manipulations.
+  */
+-static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
++static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)     
+ {
+       int i;
+       __u8 *buf = (__u8 *)1;
+-
++              
+       memset(dev->tempBuffer,0,sizeof(dev->tempBuffer));
+-
++              
+       for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
+               dev->tempBuffer[i].line = 0;    /* not in use */
+               dev->tempBuffer[i].buffer = buf =
+-                  YMALLOC_DMA(dev->nDataBytesPerChunk);
++                  YMALLOC_DMA(dev->totalBytesPerChunk);
+       }
+-
++              
+       return buf ? YAFFS_OK : YAFFS_FAIL;
+-
++      
+ }
+-static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
++__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
+ {
+       int i, j;
++
++      dev->tempInUse++;
++      if(dev->tempInUse > dev->maxTemp)
++              dev->maxTemp = dev->tempInUse;
++
+       for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+               if (dev->tempBuffer[i].line == 0) {
+                       dev->tempBuffer[i].line = lineNo;
+@@ -242,10 +251,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D
+ }
+-static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
++void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
+                                   int lineNo)
+ {
+       int i;
++      
++      dev->tempInUse--;
++      
+       for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+               if (dev->tempBuffer[i].buffer == buffer) {
+                       dev->tempBuffer[i].line = 0;
+@@ -337,7 +349,7 @@ static Y_INLINE void yaffs_ClearChunkBit
+ static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
+ {
+       __u8 *blkBits = yaffs_BlockBits(dev, blk);
+-
++      
+       yaffs_VerifyChunkBitId(dev,blk,chunk);
+       blkBits[chunk / 8] |= (1 << (chunk & 7));
+@@ -375,16 +387,16 @@ static int yaffs_CountChunkBits(yaffs_De
+                               n++;
+                       x >>=1;
+               }
+-
++                      
+               blkBits++;
+       }
+       return n;
+ }
+-/*
++/* 
+  * Verification code
+  */
+-
++ 
+ static int yaffs_SkipVerification(yaffs_Device *dev)
+ {
+       return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
+@@ -417,14 +429,14 @@ static void yaffs_VerifyBlock(yaffs_Devi
+ {
+       int actuallyUsed;
+       int inUse;
+-
++      
+       if(yaffs_SkipVerification(dev))
+               return;
+-
++              
+       /* Report illegal runtime states */
+-      if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
++      if(bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
+               T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState));
+-
++              
+       switch(bi->blockState){
+        case YAFFS_BLOCK_STATE_UNKNOWN:
+        case YAFFS_BLOCK_STATE_SCANNING:
+@@ -432,43 +444,44 @@ static void yaffs_VerifyBlock(yaffs_Devi
+               T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR),
+               n,blockStateName[bi->blockState]));
+       }
+-
++      
+       /* Check pages in use and soft deletions are legal */
+-
++      
+       actuallyUsed = bi->pagesInUse - bi->softDeletions;
+-
++      
+       if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock ||
+          bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock ||
+          actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock)
+               T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR),
+               n,bi->pagesInUse,bi->softDeletions));
+-
+-
++      
++              
+       /* Check chunk bitmap legal */
+       inUse = yaffs_CountChunkBits(dev,n);
+       if(inUse != bi->pagesInUse)
+               T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR),
+                       n,bi->pagesInUse,inUse));
+-
++      
+       /* Check that the sequence number is valid.
+-       * Ten million is legal, but is very unlikely
++       * Ten million is legal, but is very unlikely 
+        */
+-      if(dev->isYaffs2 &&
++      if(dev->isYaffs2 && 
+          (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) &&
+          (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 ))
+               T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR),
+               n,bi->sequenceNumber));
+-
++              
+ }
+ static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
+ {
+       yaffs_VerifyBlock(dev,bi,n);
+-
++      
+       /* After collection the block should be in the erased state */
+-      /* TODO: This will need to change if we do partial gc */
+-
+-      if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
++      /* This will need to change if we do partial gc */
++      
++      if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING &&
++         bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
+               T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR),
+                       n,bi->blockState));
+       }
+@@ -479,28 +492,28 @@ static void yaffs_VerifyBlocks(yaffs_Dev
+       int i;
+       int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
+       int nIllegalBlockStates = 0;
+-
++      
+       if(yaffs_SkipVerification(dev))
+               return;
+       memset(nBlocksPerState,0,sizeof(nBlocksPerState));
+-
++              
+       for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){
+               yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
+               yaffs_VerifyBlock(dev,bi,i);
+-              if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
++              if(bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
+                       nBlocksPerState[bi->blockState]++;
+               else
+                       nIllegalBlockStates++;
+-
++                                      
+       }
+-
++      
+       T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
+       T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR)));
+-
++      
+       T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates));
+       if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
+               T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR)));
+@@ -509,17 +522,17 @@ static void yaffs_VerifyBlocks(yaffs_Dev
+               T(YAFFS_TRACE_VERIFY,
+                 (TSTR("%s %d blocks"TENDSTR),
+                 blockStateName[i],nBlocksPerState[i]));
+-
++      
+       if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])
+               T(YAFFS_TRACE_VERIFY,
+                (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),
+                dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]));
+-
++               
+       if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])
+               T(YAFFS_TRACE_VERIFY,
+                (TSTR("Erased block count wrong dev %d count %d"TENDSTR),
+                dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]));
+-
++               
+       if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)
+               T(YAFFS_TRACE_VERIFY,
+                (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),
+@@ -535,16 +548,16 @@ static void yaffs_VerifyBlocks(yaffs_Dev
+  */
+ static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
+ {
+-      if(yaffs_SkipVerification(obj->myDev))
++      if(obj && yaffs_SkipVerification(obj->myDev))
+               return;
+-
++              
+       if(!(tags && obj && oh)){
+               T(YAFFS_TRACE_VERIFY,
+                               (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR),
+                               (__u32)tags,(__u32)obj,(__u32)oh));
+               return;
+       }
+-
++      
+       if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
+          oh->type > YAFFS_OBJECT_TYPE_MAX)
+               T(YAFFS_TRACE_VERIFY,
+@@ -559,25 +572,25 @@ static void yaffs_VerifyObjectHeader(yaf
+       /*
+        * Check that the object's parent ids match if parentCheck requested.
+-       *
++       * 
+        * Tests do not apply to the root object.
+        */
+-
++      
+       if(parentCheck && tags->objectId > 1 && !obj->parent)
+               T(YAFFS_TRACE_VERIFY,
+                (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),
+                tags->objectId, oh->parentObjectId));
+-
+-
++              
++      
+       if(parentCheck && obj->parent &&
+-         oh->parentObjectId != obj->parent->objectId &&
++         oh->parentObjectId != obj->parent->objectId && 
+          (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||
+           obj->parent->objectId != YAFFS_OBJECTID_DELETED))
+               T(YAFFS_TRACE_VERIFY,
+                (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),
+                tags->objectId, oh->parentObjectId, obj->parent->objectId));
+-
+-
++              
++      
+       if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */
+               T(YAFFS_TRACE_VERIFY,
+               (TSTR("Obj %d header name is NULL"TENDSTR),
+@@ -597,7 +610,6 @@ static int yaffs_VerifyTnodeWorker(yaffs
+       int i;
+       yaffs_Device *dev = obj->myDev;
+       int ok = 1;
+-      int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+       if (tn) {
+               if (level > 0) {
+@@ -611,15 +623,14 @@ static int yaffs_VerifyTnodeWorker(yaffs
+                               }
+                       }
+               } else if (level == 0) {
+-                      int i;
+                       yaffs_ExtendedTags tags;
+                       __u32 objectId = obj->objectId;
+-
++                      
+                       chunkOffset <<=  YAFFS_TNODES_LEVEL0_BITS;
+-
++                      
+                       for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
+                               __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+-
++                              
+                               if(theChunk > 0){
+                                       /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
+                                       yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
+@@ -646,18 +657,20 @@ static void yaffs_VerifyFile(yaffs_Objec
+       __u32 lastChunk;
+       __u32 x;
+       __u32 i;
+-      int ok;
+       yaffs_Device *dev;
+       yaffs_ExtendedTags tags;
+       yaffs_Tnode *tn;
+       __u32 objectId;
+-
+-      if(obj && yaffs_SkipVerification(obj->myDev))
++      
++      if(!obj)
+               return;
++      if(yaffs_SkipVerification(obj->myDev))
++              return;
++      
+       dev = obj->myDev;
+       objectId = obj->objectId;
+-
++      
+       /* Check file size is consistent with tnode depth */
+       lastChunk =  obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;
+       x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;
+@@ -666,23 +679,23 @@ static void yaffs_VerifyFile(yaffs_Objec
+               x >>= YAFFS_TNODES_INTERNAL_BITS;
+               requiredTallness++;
+       }
+-
++      
+       actualTallness = obj->variant.fileVariant.topLevel;
+-
++      
+       if(requiredTallness > actualTallness )
+               T(YAFFS_TRACE_VERIFY,
+               (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),
+                obj->objectId,actualTallness, requiredTallness));
+-
+-
+-      /* Check that the chunks in the tnode tree are all correct.
++      
++      
++      /* Check that the chunks in the tnode tree are all correct. 
+        * We do this by scanning through the tnode tree and
+        * checking the tags for every chunk match.
+        */
+       if(yaffs_SkipNANDVerification(dev))
+               return;
+-
++              
+       for(i = 1; i <= lastChunk; i++){
+               tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i);
+@@ -703,18 +716,12 @@ static void yaffs_VerifyFile(yaffs_Objec
+ }
+-static void yaffs_VerifyDirectory(yaffs_Object *obj)
+-{
+-      if(obj && yaffs_SkipVerification(obj->myDev))
+-              return;
+-
+-}
+ static void yaffs_VerifyHardLink(yaffs_Object *obj)
+ {
+       if(obj && yaffs_SkipVerification(obj->myDev))
+               return;
+-
++              
+       /* Verify sane equivalent object */
+ }
+@@ -722,7 +729,7 @@ static void yaffs_VerifySymlink(yaffs_Ob
+ {
+       if(obj && yaffs_SkipVerification(obj->myDev))
+               return;
+-
++              
+       /* Verify symlink string */
+ }
+@@ -735,69 +742,77 @@ static void yaffs_VerifySpecial(yaffs_Ob
+ static void yaffs_VerifyObject(yaffs_Object *obj)
+ {
+       yaffs_Device *dev;
+-
++      
+       __u32 chunkMin;
+       __u32 chunkMax;
+-
++      
+       __u32 chunkIdOk;
+-      __u32 chunkIsLive;
+-
++      __u32 chunkInRange;
++      __u32 chunkShouldNotBeDeleted;
++      __u32 chunkValid; 
++      
+       if(!obj)
+               return;
+-
++              
++      if(obj->beingCreated)
++              return;
++      
+       dev = obj->myDev;
+-
++      
+       if(yaffs_SkipVerification(dev))
+               return;
+-
++              
+       /* Check sane object header chunk */
+       chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
+       chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
+-      chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax);
+-      chunkIsLive = chunkIdOk &&
++      chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
++      chunkIdOk = chunkInRange || obj->hdrChunk == 0;
++      chunkValid  =  chunkInRange &&
+                       yaffs_CheckChunkBit(dev,
+-                                          obj->chunkId / dev->nChunksPerBlock,
+-                                          obj->chunkId % dev->nChunksPerBlock);
++                                          obj->hdrChunk / dev->nChunksPerBlock,
++                                          obj->hdrChunk % dev->nChunksPerBlock);
++      chunkShouldNotBeDeleted = chunkInRange && !chunkValid;
++
+       if(!obj->fake &&
+-          (!chunkIdOk || !chunkIsLive)) {
++          (!chunkIdOk || chunkShouldNotBeDeleted)) {
+          T(YAFFS_TRACE_VERIFY,
+          (TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
+-         obj->objectId,obj->chunkId,
++         obj->objectId,obj->hdrChunk,
+          chunkIdOk ? "" : ",out of range",
+-         chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
++         chunkShouldNotBeDeleted ? ",marked as deleted" : ""));
+       }
+-
+-      if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
++      
++      if(chunkValid &&!yaffs_SkipNANDVerification(dev)) {
+               yaffs_ExtendedTags tags;
+               yaffs_ObjectHeader *oh;
+               __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
+-
++              
+               oh = (yaffs_ObjectHeader *)buffer;
+-              yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
++              yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags);
+               yaffs_VerifyObjectHeader(obj,oh,&tags,1);
+-
++              
+               yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
+       }
+-
++      
+       /* Verify it has a parent */
+       if(obj && !obj->fake &&
+          (!obj->parent || obj->parent->myDev != dev)){
+          T(YAFFS_TRACE_VERIFY,
+          (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),
+-         obj->objectId,obj->parent));
++         obj->objectId,obj->parent));    
+       }
+-
++      
+       /* Verify parent is a directory */
+       if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
+          T(YAFFS_TRACE_VERIFY,
+          (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),
+-         obj->objectId,obj->parent->variantType));
++         obj->objectId,obj->parent->variantType));       
+       }
+-
++      
+       switch(obj->variantType){
+       case YAFFS_OBJECT_TYPE_FILE:
+               yaffs_VerifyFile(obj);
+@@ -818,31 +833,31 @@ static void yaffs_VerifyObject(yaffs_Obj
+       default:
+               T(YAFFS_TRACE_VERIFY,
+               (TSTR("Obj %d has illegaltype %d"TENDSTR),
+-              obj->objectId,obj->variantType));
++              obj->objectId,obj->variantType));          
+               break;
+       }
+-
+-
++      
++      
+ }
+ static void yaffs_VerifyObjects(yaffs_Device *dev)
+ {
+-      yaffs_Object *obj;
+-      int i;
+-      struct list_head *lh;
+-
+-      if(yaffs_SkipVerification(dev))
+-              return;
+-
+-      /* Iterate through the objects in each hash entry */
+-
+-       for(i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++){
+-              list_for_each(lh, &dev->objectBucket[i].list) {
+-                      if (lh) {
+-                              obj = list_entry(lh, yaffs_Object, hashLink);
+-                              yaffs_VerifyObject(obj);
+-                      }
+-              }
++        yaffs_Object *obj;
++        int i;
++        struct ylist_head *lh;
++
++        if(yaffs_SkipVerification(dev))
++                return;
++      
++        /* Iterate through the objects in each hash entry */
++         
++         for(i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++){
++                ylist_for_each(lh, &dev->objectBucket[i].list) {
++                        if (lh) {
++                                obj = ylist_entry(lh, yaffs_Object, hashLink);
++                                yaffs_VerifyObject(obj);
++                        }
++                }
+        }
+ }
+@@ -851,7 +866,7 @@ static void yaffs_VerifyObjects(yaffs_De
+ /*
+  *  Simple hash function. Needs to have a reasonable spread
+  */
+-
++ 
+ static Y_INLINE int yaffs_HashFunction(int n)
+ {
+       n = abs(n);
+@@ -859,9 +874,10 @@ static Y_INLINE int yaffs_HashFunction(i
+ }
+ /*
+- * Access functions to useful fake objects
++ * Access functions to useful fake objects.
++ * Note that root might have a presence in NAND if permissions are set.
+  */
+-
++ 
+ yaffs_Object *yaffs_Root(yaffs_Device * dev)
+ {
+       return dev->rootDir;
+@@ -876,7 +892,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Dev
+ /*
+  *  Erased NAND checking functions
+  */
+-
++ 
+ int yaffs_CheckFF(__u8 * buffer, int nBytes)
+ {
+       /* Horrible, slow implementation */
+@@ -898,10 +914,10 @@ static int yaffs_CheckChunkErased(struct
+       int result;
+       result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
+-
++      
+       if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
+               retval = YAFFS_FAIL;
+-
++              
+       if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
+               T(YAFFS_TRACE_NANDACCESS,
+@@ -915,7 +931,6 @@ static int yaffs_CheckChunkErased(struct
+ }
+-
+ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
+                                            const __u8 * data,
+                                            yaffs_ExtendedTags * tags,
+@@ -992,7 +1007,11 @@ static int yaffs_WriteNewChunkWithTagsTo
+               /* Copy the data into the robustification buffer */
+               yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
+-      } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts);
++      } while (writeOk != YAFFS_OK && 
++              (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
++      
++      if(!writeOk)
++              chunk = -1;
+       if (attempts > 1) {
+               T(YAFFS_TRACE_ERROR,
+@@ -1008,13 +1027,13 @@ static int yaffs_WriteNewChunkWithTagsTo
+ /*
+  * Block retiring for handling a broken block.
+  */
+-
++ 
+ static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
+ {
+       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
+       yaffs_InvalidateCheckpoint(dev);
+-
++      
+       yaffs_MarkBlockBad(dev, blockInNAND);
+       bi->blockState = YAFFS_BLOCK_STATE_DEAD;
+@@ -1028,7 +1047,7 @@ static void yaffs_RetireBlock(yaffs_Devi
+  * Functions for robustisizing TODO
+  *
+  */
+-
++ 
+ static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
+                                    const __u8 * data,
+                                    const yaffs_ExtendedTags * tags)
+@@ -1046,13 +1065,13 @@ void yaffs_HandleChunkError(yaffs_Device
+               bi->gcPrioritise = 1;
+               dev->hasPendingPrioritisedGCs = 1;
+               bi->chunkErrorStrikes ++;
+-
++              
+               if(bi->chunkErrorStrikes > 3){
+                       bi->needsRetiring = 1; /* Too many stikes, so retire this */
+                       T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
+               }
+-
++              
+       }
+ }
+@@ -1063,30 +1082,30 @@ static void yaffs_HandleWriteChunkError(
+       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
+       yaffs_HandleChunkError(dev,bi);
+-
+-
++              
++      
+       if(erasedOk ) {
+               /* Was an actual write failure, so mark the block for retirement  */
+               bi->needsRetiring = 1;
+               T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+                 (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
+-
++              
+       }
+-
++      
+       /* Delete the chunk */
+       yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
+ }
+-/*---------------- Name handling functions ------------*/
++/*---------------- Name handling functions ------------*/ 
+ static __u16 yaffs_CalcNameSum(const YCHAR * name)
+ {
+       __u16 sum = 0;
+       __u16 i = 1;
+-      YUCHAR *bname = (YUCHAR *) name;
++      const YUCHAR *bname = (const YUCHAR *) name;
+       if (bname) {
+               while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
+@@ -1099,12 +1118,14 @@ static __u16 yaffs_CalcNameSum(const YCH
+                       bname++;
+               }
+       }
++      
+       return sum;
+ }
+ static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
+ {
+ #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
++      memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); 
+       if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
+               yaffs_strcpy(obj->shortName, name);
+       } else {
+@@ -1120,7 +1141,7 @@ static void yaffs_SetObjectName(yaffs_Ob
+  * The list is hooked together using the first pointer
+  * in the tnode.
+  */
+-
++ 
+ /* yaffs_CreateTnodes creates a bunch more tnodes and
+  * adds them to the tnode free list.
+  * Don't use this function directly
+@@ -1138,11 +1159,15 @@ static int yaffs_CreateTnodes(yaffs_Devi
+       if (nTnodes < 1)
+               return YAFFS_OK;
+-
++              
+       /* Calculate the tnode size in bytes for variable width tnode support.
+        * Must be a multiple of 32-bits  */
+       tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
++      if(tnodeSize < sizeof(yaffs_Tnode))
++              tnodeSize = sizeof(yaffs_Tnode);
++              
++
+       /* make these things */
+       newTnodes = YMALLOC(nTnodes * tnodeSize);
+@@ -1175,7 +1200,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
+               next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
+               curr->internal[0] = next;
+       }
+-
++      
+       curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
+       curr->internal[0] = dev->freeTnodes;
+       dev->freeTnodes = (yaffs_Tnode *)mem;
+@@ -1190,7 +1215,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
+        * NB If we can't add this to the management list it isn't fatal
+        * but it just means we can't free this bunch of tnodes later.
+        */
+-
++       
+       tnl = YMALLOC(sizeof(yaffs_TnodeList));
+       if (!tnl) {
+               T(YAFFS_TRACE_ERROR,
+@@ -1233,17 +1258,23 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya
+               dev->nFreeTnodes--;
+       }
++      dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
++
+       return tn;
+ }
+ static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
+ {
+       yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
++      int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
++      if(tnodeSize < sizeof(yaffs_Tnode))
++              tnodeSize = sizeof(yaffs_Tnode);
++      
+       if(tn)
+-              memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
++              memset(tn, 0, tnodeSize);
+-      return tn;
++      return tn;      
+ }
+ /* FreeTnode frees up a tnode and puts it back on the free list */
+@@ -1262,6 +1293,8 @@ static void yaffs_FreeTnode(yaffs_Device
+               dev->freeTnodes = tn;
+               dev->nFreeTnodes++;
+       }
++      dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
++      
+ }
+ static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
+@@ -1299,19 +1332,19 @@ void yaffs_PutLevel0Tnode(yaffs_Device *
+   __u32 bitInWord;
+   __u32 wordInMap;
+   __u32 mask;
+-
++  
+   pos &= YAFFS_TNODES_LEVEL0_MASK;
+   val >>= dev->chunkGroupBits;
+-
++  
+   bitInMap = pos * dev->tnodeWidth;
+   wordInMap = bitInMap /32;
+   bitInWord = bitInMap & (32 -1);
+-
++  
+   mask = dev->tnodeMask << bitInWord;
+-
++  
+   map[wordInMap] &= ~mask;
+   map[wordInMap] |= (mask & (val << bitInWord));
+-
++  
+   if(dev->tnodeWidth > (32-bitInWord)) {
+     bitInWord = (32 - bitInWord);
+     wordInMap++;;
+@@ -1328,24 +1361,24 @@ static __u32 yaffs_GetChunkGroupBase(yaf
+   __u32 bitInWord;
+   __u32 wordInMap;
+   __u32 val;
+-
++  
+   pos &= YAFFS_TNODES_LEVEL0_MASK;
+-
++  
+   bitInMap = pos * dev->tnodeWidth;
+   wordInMap = bitInMap /32;
+   bitInWord = bitInMap & (32 -1);
+-
++  
+   val = map[wordInMap] >> bitInWord;
+-
++  
+   if(dev->tnodeWidth > (32-bitInWord)) {
+     bitInWord = (32 - bitInWord);
+     wordInMap++;;
+     val |= (map[wordInMap] << bitInWord);
+   }
+-
++  
+   val &= dev->tnodeMask;
+   val <<= dev->chunkGroupBits;
+-
++  
+   return val;
+ }
+@@ -1394,7 +1427,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
+       while (level > 0 && tn) {
+               tn = tn->
+                   internal[(chunkId >>
+-                             ( YAFFS_TNODES_LEVEL0_BITS +
++                             ( YAFFS_TNODES_LEVEL0_BITS + 
+                                (level - 1) *
+                                YAFFS_TNODES_INTERNAL_BITS)
+                             ) &
+@@ -1416,7 +1449,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
+  *  If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
+  *  be plugged into the ttree.
+  */
+-
++ 
+ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
+                                              yaffs_FileStructure * fStruct,
+                                              __u32 chunkId,
+@@ -1453,7 +1486,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
+       if (requiredTallness > fStruct->topLevel) {
+               /* Not tall enough,gotta make the tree taller */
+               for (i = fStruct->topLevel; i < requiredTallness; i++) {
+-
++              
+                       tn = yaffs_GetTnode(dev);
+                       if (tn) {
+@@ -1472,7 +1505,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
+       l = fStruct->topLevel;
+       tn = fStruct->top;
+-
++      
+       if(l > 0) {
+               while (l > 0 && tn) {
+                       x = (chunkId >>
+@@ -1492,13 +1525,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
+                                       if(tn->internal[x])
+                                               yaffs_FreeTnode(dev,tn->internal[x]);
+                                       tn->internal[x] = passedTn;
+-
++                      
+                               } else if(!tn->internal[x]) {
+                                       /* Don't have one, none passed in */
+                                       tn->internal[x] = yaffs_GetTnode(dev);
+                               }
+                       }
+-
++              
+                       tn = tn->internal[x];
+                       l--;
+               }
+@@ -1539,7 +1572,7 @@ static int yaffs_FindChunkInGroup(yaffs_
+ /* DeleteWorker scans backwards through the tnode tree and deletes all the
+  * chunks and tnodes in the file
+- * Returns 1 if the tree was deleted.
++ * Returns 1 if the tree was deleted. 
+  * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
+  */
+@@ -1653,7 +1686,7 @@ static void yaffs_SoftDeleteChunk(yaffs_
+  * of the tnode.
+  * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
+  */
+-
++ 
+ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
+                                 __u32 level, int chunkOffset)
+ {
+@@ -1694,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_
+                               theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
+                               if (theChunk) {
+                                       /* Note this does not find the real chunk, only the chunk group.
+-                                       * We make an assumption that a chunk group is not larger than
++                                       * We make an assumption that a chunk group is not larger than 
+                                        * a block.
+                                        */
+                                       yaffs_SoftDeleteChunk(dev, theChunk);
+@@ -1796,7 +1829,7 @@ static int yaffs_PruneFileStructure(yaff
+               /* Now we have a tree with all the non-zero branches NULL but the height
+                * is the same as it was.
+                * Let's see if we can trim internal tnodes to shorten the tree.
+-               * We can do this if only the 0th element in the tnode is in use
++               * We can do this if only the 0th element in the tnode is in use 
+                * (ie all the non-zero are NULL)
+                */
+@@ -1850,14 +1883,14 @@ static int yaffs_CreateFreeObjects(yaffs
+                 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
+               return YAFFS_FAIL;
+       }
++      
++        /* Hook them into the free list */
++        for (i = 0; i < nObjects - 1; i++) {
++                newObjects[i].siblings.next =
++                    (struct ylist_head *)(&newObjects[i + 1]);
++        }
+-      /* Hook them into the free list */
+-      for (i = 0; i < nObjects - 1; i++) {
+-              newObjects[i].siblings.next =
+-                  (struct list_head *)(&newObjects[i + 1]);
+-      }
+-
+-      newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
++        newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
+       dev->freeObjects = newObjects;
+       dev->nFreeObjects += nObjects;
+       dev->nObjectsCreated += nObjects;
+@@ -1877,6 +1910,9 @@ static yaffs_Object *yaffs_AllocateEmpty
+ {
+       yaffs_Object *tn = NULL;
++#ifdef VALGRIND_TEST
++      tn = YMALLOC(sizeof(yaffs_Object));
++#else
+       /* If there are none left make more */
+       if (!dev->freeObjects) {
+               yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
+@@ -1887,25 +1923,40 @@ static yaffs_Object *yaffs_AllocateEmpty
+               dev->freeObjects =
+                   (yaffs_Object *) (dev->freeObjects->siblings.next);
+               dev->nFreeObjects--;
+-
++      }
++#endif
++      if(tn){
+               /* Now sweeten it up... */
+               memset(tn, 0, sizeof(yaffs_Object));
++              tn->beingCreated = 1;
++              
+               tn->myDev = dev;
+-              tn->chunkId = -1;
++              tn->hdrChunk = 0;
+               tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
+-              INIT_LIST_HEAD(&(tn->hardLinks));
+-              INIT_LIST_HEAD(&(tn->hashLink));
+-              INIT_LIST_HEAD(&tn->siblings);
++              YINIT_LIST_HEAD(&(tn->hardLinks));
++              YINIT_LIST_HEAD(&(tn->hashLink));
++              YINIT_LIST_HEAD(&tn->siblings);
++              
++
++              /* Now make the directory sane */
++              if(dev->rootDir){
++                      tn->parent = dev->rootDir;
++                      ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children);
++              }
+-              /* Add it to the lost and found directory.
+-               * NB Can't put root or lostNFound in lostNFound so
++                /* Add it to the lost and found directory.
++                 * NB Can't put root or lostNFound in lostNFound so
+                * check if lostNFound exists first
+                */
+               if (dev->lostNFoundDir) {
+                       yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
+               }
++              
++              tn->beingCreated = 0;
+       }
++      
++      dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
+       return tn;
+ }
+@@ -1917,14 +1968,14 @@ static yaffs_Object *yaffs_CreateFakeDir
+       yaffs_Object *obj =
+           yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
+       if (obj) {
+-              obj->fake = 1;          /* it is fake so it has no NAND presence... */
++              obj->fake = 1;          /* it is fake so it might have no NAND presence... */
+               obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
+               obj->unlinkAllowed = 0; /* ... or unlink it */
+               obj->deleted = 0;
+               obj->unlinked = 0;
+               obj->yst_mode = mode;
+               obj->myDev = dev;
+-              obj->chunkId = 0;       /* Not a valid chunk. */
++              obj->hdrChunk = 0;      /* Not a valid chunk. */
+       }
+       return obj;
+@@ -1934,14 +1985,14 @@ static yaffs_Object *yaffs_CreateFakeDir
+ static void yaffs_UnhashObject(yaffs_Object * tn)
+ {
+       int bucket;
+-      yaffs_Device *dev = tn->myDev;
++        yaffs_Device *dev = tn->myDev;
+-      /* If it is still linked into the bucket list, free from the list */
+-      if (!list_empty(&tn->hashLink)) {
+-              list_del_init(&tn->hashLink);
+-              bucket = yaffs_HashFunction(tn->objectId);
+-              dev->objectBucket[bucket].count--;
+-      }
++        /* If it is still linked into the bucket list, free from the list */
++        if (!ylist_empty(&tn->hashLink)) {
++                ylist_del_init(&tn->hashLink);
++                bucket = yaffs_HashFunction(tn->objectId);
++                dev->objectBucket[bucket].count--;
++        }
+ }
+@@ -1951,6 +2002,13 @@ static void yaffs_FreeObject(yaffs_Objec
+       yaffs_Device *dev = tn->myDev;
++      
++      if(tn->parent)
++              YBUG();
++      if(!ylist_empty(&tn->siblings))
++              YBUG();
++
++
+ #ifdef  __KERNEL__
+       if (tn->myInode) {
+               /* We're still hooked up to a cached inode.
+@@ -1961,12 +2019,18 @@ static void yaffs_FreeObject(yaffs_Objec
+       }
+ #endif
+-      yaffs_UnhashObject(tn);
++        yaffs_UnhashObject(tn);
++
++#ifdef VALGRIND_TEST
++      YFREE(tn);
++#else
++        /* Link into the free list. */
++        tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
++        dev->freeObjects = tn;
++        dev->nFreeObjects++;
++#endif
++      dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
+-      /* Link into the free list. */
+-      tn->siblings.next = (struct list_head *)(dev->freeObjects);
+-      dev->freeObjects = tn;
+-      dev->nFreeObjects++;
+ }
+ #ifdef __KERNEL__
+@@ -2004,12 +2068,12 @@ static void yaffs_InitialiseObjects(yaff
+       dev->allocatedObjectList = NULL;
+       dev->freeObjects = NULL;
+-      dev->nFreeObjects = 0;
++        dev->nFreeObjects = 0;
+-      for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
+-              INIT_LIST_HEAD(&dev->objectBucket[i].list);
+-              dev->objectBucket[i].count = 0;
+-      }
++        for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
++                YINIT_LIST_HEAD(&dev->objectBucket[i].list);
++                dev->objectBucket[i].count = 0;
++        }
+ }
+@@ -2055,26 +2119,26 @@ static int yaffs_CreateNewObjectNumber(y
+       /* Now find an object value that has not already been taken
+        * by scanning the list.
+-       */
++         */
+-      int found = 0;
+-      struct list_head *i;
++        int found = 0;
++        struct ylist_head *i;
+-      __u32 n = (__u32) bucket;
++        __u32 n = (__u32) bucket;
+       /* yaffs_CheckObjectHashSanity();  */
+       while (!found) {
+-              found = 1;
+-              n += YAFFS_NOBJECT_BUCKETS;
+-              if (1 || dev->objectBucket[bucket].count > 0) {
+-                      list_for_each(i, &dev->objectBucket[bucket].list) {
+-                              /* If there is already one in the list */
+-                              if (i
+-                                  && list_entry(i, yaffs_Object,
+-                                                hashLink)->objectId == n) {
+-                                      found = 0;
+-                              }
++                found = 1;
++                n += YAFFS_NOBJECT_BUCKETS;
++                if (1 || dev->objectBucket[bucket].count > 0) {
++                        ylist_for_each(i, &dev->objectBucket[bucket].list) {
++                                /* If there is already one in the list */
++                                if (i
++                                    && ylist_entry(i, yaffs_Object,
++                                                  hashLink)->objectId == n) {
++                                        found = 0;
++                                }
+                       }
+               }
+       }
+@@ -2085,27 +2149,27 @@ static int yaffs_CreateNewObjectNumber(y
+ static void yaffs_HashObject(yaffs_Object * in)
+ {
+-      int bucket = yaffs_HashFunction(in->objectId);
+-      yaffs_Device *dev = in->myDev;
++        int bucket = yaffs_HashFunction(in->objectId);
++        yaffs_Device *dev = in->myDev;
+-      list_add(&in->hashLink, &dev->objectBucket[bucket].list);
+-      dev->objectBucket[bucket].count++;
++        ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
++        dev->objectBucket[bucket].count++;
+ }
+ yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
+ {
+-      int bucket = yaffs_HashFunction(number);
+-      struct list_head *i;
+-      yaffs_Object *in;
+-
+-      list_for_each(i, &dev->objectBucket[bucket].list) {
+-              /* Look if it is in the list */
+-              if (i) {
+-                      in = list_entry(i, yaffs_Object, hashLink);
+-                      if (in->objectId == number) {
++        int bucket = yaffs_HashFunction(number);
++        struct ylist_head *i;
++        yaffs_Object *in;
++
++        ylist_for_each(i, &dev->objectBucket[bucket].list) {
++                /* Look if it is in the list */
++                if (i) {
++                        in = ylist_entry(i, yaffs_Object, hashLink);
++                        if (in->objectId == number) {
+ #ifdef __KERNEL__
+-                              /* Don't tell the VFS about this one if it is defered free */
++                                /* Don't tell the VFS about this one if it is defered free */
+                               if (in->deferedFree)
+                                       return NULL;
+ #endif
+@@ -2123,7 +2187,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
+ {
+       yaffs_Object *theObject;
+-      yaffs_Tnode *tn;
++      yaffs_Tnode *tn = NULL;
+       if (number < 0) {
+               number = yaffs_CreateNewObjectNumber(dev);
+@@ -2132,7 +2196,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
+       theObject = yaffs_AllocateEmptyObject(dev);
+       if(!theObject)
+               return NULL;
+-
++              
+       if(type == YAFFS_OBJECT_TYPE_FILE){
+               tn = yaffs_GetTnode(dev);
+               if(!tn){
+@@ -2140,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaff
+                       return NULL;
+               }
+       }
+-
+-
++              
++      
+       if (theObject) {
+               theObject->fake = 0;
+@@ -2162,19 +2226,25 @@ yaffs_Object *yaffs_CreateNewObject(yaff
+               theObject->yst_atime = theObject->yst_mtime =
+                   theObject->yst_ctime = Y_CURRENT_TIME;
+ #endif
++
++#if 0
++              theObject->sum_prev = 12345;
++              theObject->sum_trailer = 6789;
++#endif
++
+               switch (type) {
+               case YAFFS_OBJECT_TYPE_FILE:
+                       theObject->variant.fileVariant.fileSize = 0;
+                       theObject->variant.fileVariant.scannedFileSize = 0;
+                       theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */
+                       theObject->variant.fileVariant.topLevel = 0;
+-                      theObject->variant.fileVariant.top = tn;
+-                      break;
+-              case YAFFS_OBJECT_TYPE_DIRECTORY:
+-                      INIT_LIST_HEAD(&theObject->variant.directoryVariant.
+-                                     children);
+-                      break;
+-              case YAFFS_OBJECT_TYPE_SYMLINK:
++                        theObject->variant.fileVariant.top = tn;
++                        break;
++                case YAFFS_OBJECT_TYPE_DIRECTORY:
++                        YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
++                                       children);
++                        break;
++                case YAFFS_OBJECT_TYPE_SYMLINK:
+               case YAFFS_OBJECT_TYPE_HARDLINK:
+               case YAFFS_OBJECT_TYPE_SPECIAL:
+                       /* No action required */
+@@ -2205,7 +2275,7 @@ static yaffs_Object *yaffs_FindOrCreateO
+       return theObject;
+ }
+-
++                      
+ static YCHAR *yaffs_CloneString(const YCHAR * str)
+ {
+@@ -2227,7 +2297,7 @@ static YCHAR *yaffs_CloneString(const YC
+  * aliasString only has meaning for a sumlink.
+  * rdev only has meaning for devices (a subset of special objects)
+  */
+-
++ 
+ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
+                                      yaffs_Object * parent,
+                                      const YCHAR * name,
+@@ -2238,7 +2308,7 @@ static yaffs_Object *yaffs_MknodObject(y
+                                      const YCHAR * aliasString, __u32 rdev)
+ {
+       yaffs_Object *in;
+-      YCHAR *str;
++      YCHAR *str = NULL;
+       yaffs_Device *dev = parent->myDev;
+@@ -2249,6 +2319,9 @@ static yaffs_Object *yaffs_MknodObject(y
+       in = yaffs_CreateNewObject(dev, -1, type);
++      if(!in)
++              return YAFFS_FAIL;
++      
+       if(type == YAFFS_OBJECT_TYPE_SYMLINK){
+               str = yaffs_CloneString(aliasString);
+               if(!str){
+@@ -2256,11 +2329,11 @@ static yaffs_Object *yaffs_MknodObject(y
+                       return NULL;
+               }
+       }
+-
+-
++      
++      
+       if (in) {
+-              in->chunkId = -1;
++              in->hdrChunk = 0;
+               in->valid = 1;
+               in->variantType = type;
+@@ -2293,13 +2366,13 @@ static yaffs_Object *yaffs_MknodObject(y
+                       break;
+               case YAFFS_OBJECT_TYPE_HARDLINK:
+                       in->variant.hardLinkVariant.equivalentObject =
+-                          equivalentObject;
+-                      in->variant.hardLinkVariant.equivalentObjectId =
+-                          equivalentObject->objectId;
+-                      list_add(&in->hardLinks, &equivalentObject->hardLinks);
+-                      break;
+-              case YAFFS_OBJECT_TYPE_FILE:
+-              case YAFFS_OBJECT_TYPE_DIRECTORY:
++                            equivalentObject;
++                        in->variant.hardLinkVariant.equivalentObjectId =
++                            equivalentObject->objectId;
++                        ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
++                        break;
++                case YAFFS_OBJECT_TYPE_FILE:    
++                case YAFFS_OBJECT_TYPE_DIRECTORY:
+               case YAFFS_OBJECT_TYPE_SPECIAL:
+               case YAFFS_OBJECT_TYPE_UNKNOWN:
+                       /* do nothing */
+@@ -2378,11 +2451,11 @@ static int yaffs_ChangeObjectName(yaffs_
+       if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
+               T(YAFFS_TRACE_ALWAYS,
+                 (TSTR
+-                 ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
++                 ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"
+                   TENDSTR)));
+               YBUG();
+       }
+-
++      
+       /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
+       if (obj->myDev->isYaffs2) {
+               unlinkOp = (newDir == obj->myDev->unlinkedDir);
+@@ -2395,9 +2468,9 @@ static int yaffs_ChangeObjectName(yaffs_
+       existingTarget = yaffs_FindObjectByName(newDir, newName);
+-      /* If the object is a file going into the unlinked directory,
++      /* If the object is a file going into the unlinked directory, 
+        *   then it is OK to just stuff it in since duplicate names are allowed.
+-       *   else only proceed if the new name does not exist and if we're putting
++       *   else only proceed if the new name does not exist and if we're putting 
+        *   it into a directory.
+        */
+       if ((unlinkOp ||
+@@ -2425,9 +2498,15 @@ static int yaffs_ChangeObjectName(yaffs_
+ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
+                      yaffs_Object * newDir, const YCHAR * newName)
+ {
+-      yaffs_Object *obj;
+-      yaffs_Object *existingTarget;
++      yaffs_Object *obj=NULL;
++      yaffs_Object *existingTarget=NULL;
+       int force = 0;
++      
++      
++      if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
++              YBUG();
++      if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
++              YBUG();
+ #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
+       /* Special case for case insemsitive systems (eg. WinCE).
+@@ -2439,29 +2518,24 @@ int yaffs_RenameObject(yaffs_Object * ol
+       }
+ #endif
+-      obj = yaffs_FindObjectByName(oldDir, oldName);
+-      /* Check new name to long. */
+-      if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
+-          yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
+-        /* ENAMETOOLONG */
+-        return YAFFS_FAIL;
+-      else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
+-               yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
++      else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
+         /* ENAMETOOLONG */
+         return YAFFS_FAIL;
++      obj = yaffs_FindObjectByName(oldDir, oldName);
++
+       if (obj && obj->renameAllowed) {
+               /* Now do the handling for an existing target, if there is one */
+-              existingTarget = yaffs_FindObjectByName(newDir, newName);
+-              if (existingTarget &&
+-                  existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
+-                  !list_empty(&existingTarget->variant.directoryVariant.children)) {
+-                      /* There is a target that is a non-empty directory, so we fail */
+-                      return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
+-              } else if (existingTarget && existingTarget != obj) {
+-                      /* Nuke the target first, using shadowing,
++                existingTarget = yaffs_FindObjectByName(newDir, newName);
++                if (existingTarget &&
++                    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
++                    !ylist_empty(&existingTarget->variant.directoryVariant.children)) {
++                        /* There is a target that is a non-empty directory, so we fail */
++                        return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
++                } else if (existingTarget && existingTarget != obj) {
++                      /* Nuke the target first, using shadowing, 
+                        * but only if it isn't the same object
+                        */
+                       yaffs_ChangeObjectName(obj, newDir, newName, force,
+@@ -2479,10 +2553,10 @@ int yaffs_RenameObject(yaffs_Object * ol
+ static int yaffs_InitialiseBlocks(yaffs_Device * dev)
+ {
+       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
+-
++      
+       dev->blockInfo = NULL;
+       dev->chunkBits = NULL;
+-
++      
+       dev->allocationBlock = -1;      /* force it to get a new one */
+       /* If the first allocation strategy fails, thry the alternate one */
+@@ -2493,9 +2567,9 @@ static int yaffs_InitialiseBlocks(yaffs_
+       }
+       else
+               dev->blockInfoAlt = 0;
+-
++              
+       if(dev->blockInfo){
+-
++      
+               /* Set up dynamic blockinfo stuff. */
+               dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
+               dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
+@@ -2506,7 +2580,7 @@ static int yaffs_InitialiseBlocks(yaffs_
+               else
+                       dev->chunkBitsAlt = 0;
+       }
+-
++      
+       if (dev->blockInfo && dev->chunkBits) {
+               memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
+               memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
+@@ -2527,7 +2601,7 @@ static void yaffs_DeinitialiseBlocks(yaf
+       dev->blockInfoAlt = 0;
+       dev->blockInfo = NULL;
+-
++      
+       if(dev->chunkBitsAlt && dev->chunkBits)
+               YFREE_ALT(dev->chunkBits);
+       else if(dev->chunkBits)
+@@ -2591,14 +2665,14 @@ static int yaffs_FindBlockForGarbageColl
+       int prioritised=0;
+       yaffs_BlockInfo *bi;
+       int pendingPrioritisedExist = 0;
+-
++      
+       /* First let's see if we need to grab a prioritised block */
+       if(dev->hasPendingPrioritisedGCs){
+               for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
+                       bi = yaffs_GetBlockInfo(dev, i);
+                       //yaffs_VerifyBlock(dev,bi,i);
+-
++                      
+                       if(bi->gcPrioritise) {
+                               pendingPrioritisedExist = 1;
+                               if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
+@@ -2610,7 +2684,7 @@ static int yaffs_FindBlockForGarbageColl
+                               }
+                       }
+               }
+-
++              
+               if(!pendingPrioritisedExist) /* None found, so we can clear this */
+                       dev->hasPendingPrioritisedGCs = 0;
+       }
+@@ -2662,7 +2736,7 @@ static int yaffs_FindBlockForGarbageColl
+                       dirtiest = b;
+                       pagesInUse = 0;
+               }
+-              else
++              else 
+ #endif
+               if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
+@@ -2699,11 +2773,11 @@ static void yaffs_BlockBecameDirty(yaffs
+       /* If the block is still healthy erase it and mark as clean.
+        * If the block has had a data failure, then retire it.
+        */
+-
++       
+       T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
+               (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
+               blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
+-
++              
+       bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
+       if (!bi->needsRetiring) {
+@@ -2716,7 +2790,7 @@ static void yaffs_BlockBecameDirty(yaffs
+               }
+       }
+-      if (erasedOk &&
++      if (erasedOk && 
+           ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) {
+               int i;
+               for (i = 0; i < dev->nChunksPerBlock; i++) {
+@@ -2763,11 +2837,11 @@ static int yaffs_FindBlockForAllocation(
+                * Can't get space to gc
+                */
+               T(YAFFS_TRACE_ERROR,
+-                (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
++                (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));
+               return -1;
+       }
+-
++      
+       /* Find an empty block. */
+       for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
+@@ -2794,13 +2868,48 @@ static int yaffs_FindBlockForAllocation(
+       T(YAFFS_TRACE_ALWAYS,
+         (TSTR
+-         ("yaffs tragedy: no more eraased blocks, but there should have been %d"
++         ("yaffs tragedy: no more erased blocks, but there should have been %d"
+           TENDSTR), dev->nErasedBlocks));
+       return -1;
+ }
++
++static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
++{
++      if(!dev->nCheckpointBlocksRequired &&
++         dev->isYaffs2){
++              /* Not a valid value so recalculate */
++              int nBytes = 0;
++              int nBlocks;
++              int devBlocks = (dev->endBlock - dev->startBlock + 1);
++              int tnodeSize;
++
++              tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
++
++              if(tnodeSize < sizeof(yaffs_Tnode))
++                      tnodeSize = sizeof(yaffs_Tnode);
++              
++              nBytes += sizeof(yaffs_CheckpointValidity);
++              nBytes += sizeof(yaffs_CheckpointDevice);
++              nBytes += devBlocks * sizeof(yaffs_BlockInfo);
++              nBytes += devBlocks * dev->chunkBitmapStride;
++              nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects);
++              nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes);
++              nBytes += sizeof(yaffs_CheckpointValidity);
++              nBytes += sizeof(__u32); /* checksum*/
++      
++              /* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
++      
++              nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3;
++      
++              dev->nCheckpointBlocksRequired = nBlocks;
++      }
++
++      return dev->nCheckpointBlocksRequired;
++}
++
+ // Check if there's space to allocate...
+ // Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
+ static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
+@@ -2808,13 +2917,18 @@ static int yaffs_CheckSpaceForAllocation
+       int reservedChunks;
+       int reservedBlocks = dev->nReservedBlocks;
+       int checkpointBlocks;
+-
+-      checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
+-      if(checkpointBlocks < 0)
+-              checkpointBlocks = 0;
+-
++      
++      if(dev->isYaffs2){
++              checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - 
++                                  dev->blocksInCheckpoint;
++              if(checkpointBlocks < 0)
++                      checkpointBlocks = 0;
++      } else {
++              checkpointBlocks =0;
++      }
++      
+       reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
+-
++      
+       return (dev->nFreeChunks > reservedChunks);
+ }
+@@ -2861,10 +2975,10 @@ static int yaffs_AllocateChunk(yaffs_Dev
+               if(blockUsedPtr)
+                       *blockUsedPtr = bi;
+-
++                      
+               return retVal;
+       }
+-
++      
+       T(YAFFS_TRACE_ERROR,
+         (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
+@@ -2885,17 +2999,17 @@ static int yaffs_GetErasedChunks(yaffs_D
+ }
+-static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
++static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlock)
+ {
+       int oldChunk;
+       int newChunk;
+-      int chunkInBlock;
+       int markNAND;
+       int retVal = YAFFS_OK;
+       int cleanups = 0;
+       int i;
+       int isCheckpointBlock;
+       int matchingChunk;
++      int maxCopies;
+       int chunksBefore = yaffs_GetErasedChunks(dev);
+       int chunksAfter;
+@@ -2907,12 +3021,15 @@ static int yaffs_GarbageCollectBlock(yaf
+       yaffs_Object *object;
+       isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
+-
++      
+       bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
+       T(YAFFS_TRACE_TRACING,
+-        (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
+-         bi->pagesInUse, bi->hasShrinkHeader));
++        (TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR), 
++        block,
++        bi->pagesInUse,
++        bi->hasShrinkHeader,
++        wholeBlock));
+       /*yaffs_VerifyFreeChunks(dev); */
+@@ -2935,16 +3052,23 @@ static int yaffs_GarbageCollectBlock(yaf
+       } else {
+               __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
+-
++              
+               yaffs_VerifyBlock(dev,bi,block);
+-              for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
+-                   chunkInBlock < dev->nChunksPerBlock
+-                   && yaffs_StillSomeChunkBits(dev, block);
+-                   chunkInBlock++, oldChunk++) {
+-                      if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
++              maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10;
++              oldChunk = block * dev->nChunksPerBlock + dev->gcChunk;
++              
++              for ( /* init already done */;
++                   retVal == YAFFS_OK &&
++                   dev->gcChunk < dev->nChunksPerBlock &&
++                   (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING)&&
++                   maxCopies > 0;
++                   dev->gcChunk++, oldChunk++) {
++                      if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) {
+                               /* This page is in use and might need to be copied off */
++                              
++                              maxCopies--;
+                               markNAND = 1;
+@@ -2959,23 +3083,23 @@ static int yaffs_GarbageCollectBlock(yaf
+                               T(YAFFS_TRACE_GC_DETAIL,
+                                 (TSTR
+-                                 ("Collecting page %d, %d %d %d " TENDSTR),
+-                                 chunkInBlock, tags.objectId, tags.chunkId,
++                                 ("Collecting chunk in block %d, %d %d %d " TENDSTR),
++                                 dev->gcChunk, tags.objectId, tags.chunkId,
+                                  tags.byteCount));
+-
++                                 
+                               if(object && !yaffs_SkipVerification(dev)){
+                                       if(tags.chunkId == 0)
+-                                              matchingChunk = object->chunkId;
++                                              matchingChunk = object->hdrChunk;
+                                       else if(object->softDeleted)
+                                               matchingChunk = oldChunk; /* Defeat the test */
+                                       else
+                                               matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL);
+-
++                                      
+                                       if(oldChunk != matchingChunk)
+                                               T(YAFFS_TRACE_ERROR,
+                                                 (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR),
+                                                 oldChunk,matchingChunk,tags.objectId, tags.chunkId));
+-
++                                              
+                               }
+                               if (!object) {
+@@ -2986,11 +3110,13 @@ static int yaffs_GarbageCollectBlock(yaf
+                                           tags.objectId, tags.chunkId, tags.byteCount));
+                               }
+-                              if (object && object->deleted
+-                                  && tags.chunkId != 0) {
+-                                      /* Data chunk in a deleted file, throw it away
++                              if (object && 
++                                  object->deleted &&
++                                  object->softDeleted &&
++                                  tags.chunkId != 0) {
++                                      /* Data chunk in a soft deleted file, throw it away
+                                        * It's a soft deleted data chunk,
+-                                       * No need to copy this, just forget about it and
++                                       * No need to copy this, just forget about it and 
+                                        * fix up the object.
+                                        */
+@@ -3009,7 +3135,7 @@ static int yaffs_GarbageCollectBlock(yaf
+                                       /* Deleted object header with no data chunks.
+                                        * Can be discarded and the file deleted.
+                                        */
+-                                      object->chunkId = 0;
++                                      object->hdrChunk = 0;
+                                       yaffs_FreeTnode(object->myDev,
+                                                       object->variant.
+                                                       fileVariant.top);
+@@ -3037,10 +3163,9 @@ static int yaffs_GarbageCollectBlock(yaf
+                                               yaffs_ObjectHeader *oh;
+                                               oh = (yaffs_ObjectHeader *)buffer;
+                                               oh->isShrink = 0;
+-                                              oh->shadowsObject = -1;
+                                               tags.extraShadows = 0;
+                                               tags.extraIsShrinkHeader = 0;
+-
++                                              
+                                               yaffs_VerifyObjectHeader(object,oh,&tags,1);
+                                       }
+@@ -3055,7 +3180,7 @@ static int yaffs_GarbageCollectBlock(yaf
+                                               if (tags.chunkId == 0) {
+                                                       /* It's a header */
+-                                                      object->chunkId =  newChunk;
++                                                      object->hdrChunk =  newChunk;
+                                                       object->serial =   tags.serialNumber;
+                                               } else {
+                                                       /* It's a data chunk */
+@@ -3067,12 +3192,14 @@ static int yaffs_GarbageCollectBlock(yaf
+                                       }
+                               }
+-                              yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
++                              if(retVal == YAFFS_OK)
++                                      yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
+                       }
+               }
+               yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
++              
+               /* Do any required cleanups */
+@@ -3099,7 +3226,7 @@ static int yaffs_GarbageCollectBlock(yaf
+       }
+       yaffs_VerifyCollectedBlock(dev,bi,block);
+-
++        
+       if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
+               T(YAFFS_TRACE_GC,
+                 (TSTR
+@@ -3107,9 +3234,15 @@ static int yaffs_GarbageCollectBlock(yaf
+                   TENDSTR), chunksBefore, chunksAfter));
+       }
++      /* If the gc completed then clear the current gcBlock so that we find another. */
++      if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING){
++              dev->gcBlock = -1;
++              dev->gcChunk = 0;
++      }
++      
+       dev->isDoingGC = 0;
+-      return YAFFS_OK;
++      return retVal;
+ }
+ /* New garbage collector
+@@ -3127,22 +3260,22 @@ static int yaffs_CheckGarbageCollection(
+       int aggressive;
+       int gcOk = YAFFS_OK;
+       int maxTries = 0;
+-
++      
+       int checkpointBlockAdjust;
+       if (dev->isDoingGC) {
+               /* Bail out so we don't get recursive gc */
+               return YAFFS_OK;
+       }
+-
++      
+       /* This loop should pass the first time.
+        * We'll only see looping here if the erase of the collected block fails.
+        */
+       do {
+               maxTries++;
+-
+-              checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
++              
++              checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
+               if(checkpointBlockAdjust < 0)
+                       checkpointBlockAdjust = 0;
+@@ -3154,7 +3287,12 @@ static int yaffs_CheckGarbageCollection(
+                       aggressive = 0;
+               }
+-              block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
++              if(dev->gcBlock <= 0){
++                      dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive);
++                      dev->gcChunk = 0;
++              }
++              
++              block = dev->gcBlock;
+               if (block > 0) {
+                       dev->garbageCollections++;
+@@ -3167,7 +3305,7 @@ static int yaffs_CheckGarbageCollection(
+                          ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
+                          dev->nErasedBlocks, aggressive));
+-                      gcOk = yaffs_GarbageCollectBlock(dev, block);
++                      gcOk = yaffs_GarbageCollectBlock(dev,block,aggressive);
+               }
+               if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
+@@ -3176,8 +3314,9 @@ static int yaffs_CheckGarbageCollection(
+                          ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
+                           TENDSTR), dev->nErasedBlocks, maxTries, block));
+               }
+-      } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
+-               && (maxTries < 2));
++      } while ((dev->nErasedBlocks < dev->nReservedBlocks) && 
++               (block > 0) &&
++               (maxTries < 2));
+       return aggressive ? gcOk : YAFFS_OK;
+ }
+@@ -3326,11 +3465,11 @@ static int yaffs_CheckFileSanity(yaffs_O
+ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
+                                 int chunkInNAND, int inScan)
+ {
+-      /* NB inScan is zero unless scanning.
+-       * For forward scanning, inScan is > 0;
++      /* NB inScan is zero unless scanning. 
++       * For forward scanning, inScan is > 0; 
+        * for backward scanning inScan is < 0
+        */
+-
++       
+       yaffs_Tnode *tn;
+       yaffs_Device *dev = in->myDev;
+       int existingChunk;
+@@ -3354,7 +3493,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
+               return YAFFS_OK;
+       }
+-      tn = yaffs_AddOrFindLevel0Tnode(dev,
++      tn = yaffs_AddOrFindLevel0Tnode(dev, 
+                                       &in->variant.fileVariant,
+                                       chunkInInode,
+                                       NULL);
+@@ -3366,7 +3505,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
+       if (inScan != 0) {
+               /* If we're scanning then we need to test for duplicates
+-               * NB This does not need to be efficient since it should only ever
++               * NB This does not need to be efficient since it should only ever 
+                * happen when the power fails during a write, then only one
+                * chunk should ever be affected.
+                *
+@@ -3374,7 +3513,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
+                * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
+                */
+-              if (existingChunk != 0) {
++              if (existingChunk > 0) {
+                       /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
+                        *    thus we have to do a FindChunkInFile to get the real chunk id.
+                        *
+@@ -3407,18 +3546,20 @@ static int yaffs_PutChunkIntoFile(yaffs_
+                       }
+-                      /* NB The deleted flags should be false, otherwise the chunks will
++                      /* NB The deleted flags should be false, otherwise the chunks will 
+                        * not be loaded during a scan
+                        */
+-                      newSerial = newTags.serialNumber;
+-                      existingSerial = existingTags.serialNumber;
++                      if(inScan > 0) {
++                              newSerial = newTags.serialNumber;
++                              existingSerial = existingTags.serialNumber;
++                      }
+                       if ((inScan > 0) &&
+                           (in->myDev->isYaffs2 ||
+                            existingChunk <= 0 ||
+                            ((existingSerial + 1) & 3) == newSerial)) {
+-                              /* Forward scanning.
++                              /* Forward scanning.                            
+                                * Use new
+                                * Delete the old one and drop through to update the tnode
+                                */
+@@ -3459,7 +3600,7 @@ static int yaffs_ReadChunkDataFromObject
+                 (TSTR("Chunk %d not found zero instead" TENDSTR),
+                  chunkInNAND));
+               /* get sane (zero) data if you read a hole */
+-              memset(buffer, 0, in->myDev->nDataBytesPerChunk);
++              memset(buffer, 0, in->myDev->nDataBytesPerChunk);       
+               return 0;
+       }
+@@ -3474,7 +3615,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
+       if (chunkId <= 0)
+               return;
+-
++              
+       dev->nDeletions++;
+       block = chunkId / dev->nChunksPerBlock;
+@@ -3560,6 +3701,14 @@ static int yaffs_WriteChunkDataToObject(
+       newTags.serialNumber =
+           (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
+       newTags.byteCount = nBytes;
++      
++      if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){
++        T(YAFFS_TRACE_ERROR,
++        (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
++        while(1){}
++        }
++      
++      
+       newChunkId =
+           yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
+@@ -3601,11 +3750,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
+       __u8 *buffer = NULL;
+       YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
+-      yaffs_ObjectHeader *oh = NULL;
++        yaffs_ObjectHeader *oh = NULL;
++        
++        yaffs_strcpy(oldName,_Y("silly old name"));
+-      yaffs_strcpy(oldName,"silly old name");
+-      if (!in->fake || force) {
++      if (!in->fake || 
++          in == dev->rootDir || /* The rootDir should also be saved */
++          force) {
+               yaffs_CheckGarbageCollection(dev);
+               yaffs_CheckObjectDetailsLoaded(in);
+@@ -3613,14 +3765,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
+               buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
+               oh = (yaffs_ObjectHeader *) buffer;
+-              prevChunkId = in->chunkId;
++              prevChunkId = in->hdrChunk;
+-              if (prevChunkId >= 0) {
++              if (prevChunkId > 0) {
+                       result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
+                                                       buffer, &oldTags);
+-
++                      
+                       yaffs_VerifyObjectHeader(in,oh,&oldTags,0);
+-
++                                                                              
+                       memcpy(oldName, oh->name, sizeof(oh->name));
+               }
+@@ -3628,7 +3780,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
+               oh->type = in->variantType;
+               oh->yst_mode = in->yst_mode;
+-              oh->shadowsObject = shadows;
++              oh->shadowsObject = oh->inbandShadowsObject = shadows;
+ #ifdef CONFIG_YAFFS_WINCE
+               oh->win_atime[0] = in->win_atime[0];
+@@ -3717,7 +3869,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
+               if (newChunkId >= 0) {
+-                      in->chunkId = newChunkId;
++                      in->hdrChunk = newChunkId;
+                       if (prevChunkId >= 0) {
+                               yaffs_DeleteChunk(dev, prevChunkId, 1,
+@@ -3748,11 +3900,11 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
+ /*------------------------ Short Operations Cache ----------------------------------------
+  *   In many situations where there is no high level buffering (eg WinCE) a lot of
+- *   reads might be short sequential reads, and a lot of writes may be short
++ *   reads might be short sequential reads, and a lot of writes may be short 
+  *   sequential writes. eg. scanning/writing a jpeg file.
+- *   In these cases, a short read/write cache can provide a huge perfomance benefit
++ *   In these cases, a short read/write cache can provide a huge perfomance benefit 
+  *   with dumb-as-a-rock code.
+- *   In Linux, the page cache provides read buffering aand the short op cache provides write
++ *   In Linux, the page cache provides read buffering aand the short op cache provides write 
+  *   buffering.
+  *
+  *   There are a limited number (~10) of cache chunks per device so that we don't
+@@ -3765,14 +3917,14 @@ static int yaffs_ObjectHasCachedWriteDat
+       int i;
+       yaffs_ChunkCache *cache;
+       int nCaches = obj->myDev->nShortOpCaches;
+-
++      
+       for(i = 0; i < nCaches; i++){
+               cache = &dev->srCache[i];
+               if (cache->object == obj &&
+                   cache->dirty)
+                       return 1;
+       }
+-
++      
+       return 0;
+ }
+@@ -3838,7 +3990,7 @@ void yaffs_FlushEntireDeviceCache(yaffs_
+       yaffs_Object *obj;
+       int nCaches = dev->nShortOpCaches;
+       int i;
+-
++      
+       /* Find a dirty object in the cache and flush it...
+        * until there are no further dirty objects.
+        */
+@@ -3848,53 +4000,33 @@ void yaffs_FlushEntireDeviceCache(yaffs_
+                       if (dev->srCache[i].object &&
+                           dev->srCache[i].dirty)
+                               obj = dev->srCache[i].object;
+-
++                          
+               }
+               if(obj)
+                       yaffs_FlushFilesChunkCache(obj);
+-
++                      
+       } while(obj);
+-
++      
+ }
+ /* Grab us a cache chunk for use.
+- * First look for an empty one.
++ * First look for an empty one. 
+  * Then look for the least recently used non-dirty one.
+  * Then look for the least recently used dirty one...., flush and look again.
+  */
+ static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
+ {
+       int i;
+-      int usage;
+-      int theOne;
+       if (dev->nShortOpCaches > 0) {
+               for (i = 0; i < dev->nShortOpCaches; i++) {
+-                      if (!dev->srCache[i].object)
++                      if (!dev->srCache[i].object) 
+                               return &dev->srCache[i];
+               }
+-
+-              return NULL;
+-
+-              theOne = -1;
+-              usage = 0;      /* just to stop the compiler grizzling */
+-
+-              for (i = 0; i < dev->nShortOpCaches; i++) {
+-                      if (!dev->srCache[i].dirty &&
+-                          ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
+-                           theOne < 0)) {
+-                              usage = dev->srCache[i].lastUse;
+-                              theOne = i;
+-                      }
+-              }
+-
+-
+-              return theOne >= 0 ? &dev->srCache[theOne] : NULL;
+-      } else {
+-              return NULL;
+       }
++      return NULL;
+ }
+ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
+@@ -4032,14 +4164,14 @@ static void yaffs_InvalidateWholeChunkCa
+ static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
+ {
+       yaffs_CheckpointValidity cp;
+-
++      
+       memset(&cp,0,sizeof(cp));
+-
++      
+       cp.structType = sizeof(cp);
+       cp.magic = YAFFS_MAGIC;
+       cp.version = YAFFS_CHECKPOINT_VERSION;
+       cp.head = (head) ? 1 : 0;
+-
++      
+       return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
+               1 : 0;
+ }
+@@ -4048,9 +4180,9 @@ static int yaffs_ReadCheckpointValidityM
+ {
+       yaffs_CheckpointValidity cp;
+       int ok;
+-
++      
+       ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
+-
++      
+       if(ok)
+               ok = (cp.structType == sizeof(cp)) &&
+                    (cp.magic == YAFFS_MAGIC) &&
+@@ -4059,20 +4191,20 @@ static int yaffs_ReadCheckpointValidityM
+       return ok ? 1 : 0;
+ }
+-static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
++static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp, 
+                                          yaffs_Device *dev)
+ {
+       cp->nErasedBlocks = dev->nErasedBlocks;
+       cp->allocationBlock = dev->allocationBlock;
+       cp->allocationPage = dev->allocationPage;
+       cp->nFreeChunks = dev->nFreeChunks;
+-
++      
+       cp->nDeletedFiles = dev->nDeletedFiles;
+       cp->nUnlinkedFiles = dev->nUnlinkedFiles;
+       cp->nBackgroundDeletions = dev->nBackgroundDeletions;
+       cp->sequenceNumber = dev->sequenceNumber;
+       cp->oldestDirtySequence = dev->oldestDirtySequence;
+-
++      
+ }
+ static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
+@@ -4082,7 +4214,7 @@ static void yaffs_CheckpointDeviceToDevi
+       dev->allocationBlock = cp->allocationBlock;
+       dev->allocationPage = cp->allocationPage;
+       dev->nFreeChunks = cp->nFreeChunks;
+-
++      
+       dev->nDeletedFiles = cp->nDeletedFiles;
+       dev->nUnlinkedFiles = cp->nUnlinkedFiles;
+       dev->nBackgroundDeletions = cp->nBackgroundDeletions;
+@@ -4098,20 +4230,20 @@ static int yaffs_WriteCheckpointDevice(y
+       __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
+       int ok;
+-
++              
+       /* Write device runtime values*/
+       yaffs_DeviceToCheckpointDevice(&cp,dev);
+       cp.structType = sizeof(cp);
+-
++      
+       ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
+-
++      
+       /* Write block info */
+       if(ok) {
+               nBytes = nBlocks * sizeof(yaffs_BlockInfo);
+               ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
+       }
+-
+-      /* Write chunk bits */
++              
++      /* Write chunk bits */          
+       if(ok) {
+               nBytes = nBlocks * dev->chunkBitmapStride;
+               ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
+@@ -4126,28 +4258,28 @@ static int yaffs_ReadCheckpointDevice(ya
+       __u32 nBytes;
+       __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
+-      int ok;
+-
++      int ok; 
++      
+       ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
+       if(!ok)
+               return 0;
+-
++              
+       if(cp.structType != sizeof(cp))
+               return 0;
+-
+-
++              
++      
+       yaffs_CheckpointDeviceToDevice(dev,&cp);
+-
++      
+       nBytes = nBlocks * sizeof(yaffs_BlockInfo);
+-
++      
+       ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
+-
++      
+       if(!ok)
+               return 0;
+       nBytes = nBlocks * dev->chunkBitmapStride;
+-
++      
+       ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
+-
++      
+       return ok ? 1 : 0;
+ }
+@@ -4157,7 +4289,7 @@ static void yaffs_ObjectToCheckpointObje
+       cp->objectId = obj->objectId;
+       cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
+-      cp->chunkId = obj->chunkId;
++      cp->hdrChunk = obj->hdrChunk;
+       cp->variantType = obj->variantType;
+       cp->deleted = obj->deleted;
+       cp->softDeleted = obj->softDeleted;
+@@ -4167,7 +4299,7 @@ static void yaffs_ObjectToCheckpointObje
+       cp->unlinkAllowed = obj->unlinkAllowed;
+       cp->serial = obj->serial;
+       cp->nDataChunks = obj->nDataChunks;
+-
++      
+       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
+               cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
+       else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
+@@ -4178,9 +4310,9 @@ static void yaffs_CheckpointObjectToObje
+ {
+       yaffs_Object *parent;
+-
++      
+       obj->objectId = cp->objectId;
+-
++      
+       if(cp->parentId)
+               parent = yaffs_FindOrCreateObjectByNumber(
+                                       obj->myDev,
+@@ -4188,11 +4320,11 @@ static void yaffs_CheckpointObjectToObje
+                                       YAFFS_OBJECT_TYPE_DIRECTORY);
+       else
+               parent = NULL;
+-
++              
+       if(parent)
+               yaffs_AddObjectToDirectory(parent, obj);
+-      obj->chunkId = cp->chunkId;
++      obj->hdrChunk = cp->hdrChunk;
+       obj->variantType = cp->variantType;
+       obj->deleted = cp->deleted;
+       obj->softDeleted = cp->softDeleted;
+@@ -4202,13 +4334,13 @@ static void yaffs_CheckpointObjectToObje
+       obj->unlinkAllowed = cp->unlinkAllowed;
+       obj->serial = cp->serial;
+       obj->nDataChunks = cp->nDataChunks;
+-
++      
+       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
+               obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
+       else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
+               obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
+-      if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
++      if(obj->hdrChunk > 0)
+               obj->lazyLoaded = 1;
+ }
+@@ -4220,7 +4352,11 @@ static int yaffs_CheckpointTnodeWorker(y
+       int i;
+       yaffs_Device *dev = in->myDev;
+       int ok = 1;
+-      int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
++      int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
++
++      if(tnodeSize < sizeof(yaffs_Tnode))
++              tnodeSize = sizeof(yaffs_Tnode);
++      
+       if (tn) {
+               if (level > 0) {
+@@ -4235,10 +4371,9 @@ static int yaffs_CheckpointTnodeWorker(y
+                       }
+               } else if (level == 0) {
+                       __u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
+-                      /* printf("write tnode at %d\n",baseOffset); */
+                       ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
+                       if(ok)
+-                              ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
++                              ok = (yaffs_CheckpointWrite(dev,tn,tnodeSize) == tnodeSize);
+               }
+       }
+@@ -4250,17 +4385,17 @@ static int yaffs_WriteCheckpointTnodes(y
+ {
+       __u32 endMarker = ~0;
+       int ok = 1;
+-
++      
+       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
+               ok = yaffs_CheckpointTnodeWorker(obj,
+                                           obj->variant.fileVariant.top,
+                                           obj->variant.fileVariant.topLevel,
+                                           0);
+               if(ok)
+-                      ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
++                      ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == 
+                               sizeof(endMarker));
+       }
+-
++      
+       return ok ? 1 : 0;
+ }
+@@ -4272,70 +4407,72 @@ static int yaffs_ReadCheckpointTnodes(ya
+       yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
+       yaffs_Tnode *tn;
+       int nread = 0;
++      int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+-      ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
++      if(tnodeSize < sizeof(yaffs_Tnode))
++              tnodeSize = sizeof(yaffs_Tnode);
++      ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
++      
+       while(ok && (~baseChunk)){
+               nread++;
+               /* Read level 0 tnode */
+-
+-
+-              /* printf("read  tnode at %d\n",baseChunk); */
++              
++              
+               tn = yaffs_GetTnodeRaw(dev);
+               if(tn)
+-                      ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
+-                            (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
++                      ok = (yaffs_CheckpointRead(dev,tn,tnodeSize) == tnodeSize);
+               else
+                       ok = 0;
+-
++                      
+               if(tn && ok){
+                       ok = yaffs_AddOrFindLevel0Tnode(dev,
+                                                       fileStructPtr,
+                                                       baseChunk,
+                                                       tn) ? 1 : 0;
+-
++                                                      
+               }
+-
++                      
+               if(ok)
+                       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
+-
++              
+       }
+       T(YAFFS_TRACE_CHECKPOINT,(
+               TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR),
+               nread,baseChunk,ok));
+-      return ok ? 1 : 0;
++      return ok ? 1 : 0;      
+ }
+-
++ 
+ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
+ {
+       yaffs_Object *obj;
+-      yaffs_CheckpointObject cp;
+-      int i;
+-      int ok = 1;
+-      struct list_head *lh;
++        yaffs_CheckpointObject cp;
++        int i;
++        int ok = 1;
++        struct ylist_head *lh;
+-
+-      /* Iterate through the objects in each hash entry,
++        
++        /* Iterate through the objects in each hash entry,
+        * dumping them to the checkpointing stream.
+-       */
+-
+-       for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
+-              list_for_each(lh, &dev->objectBucket[i].list) {
+-                      if (lh) {
+-                              obj = list_entry(lh, yaffs_Object, hashLink);
+-                              if (!obj->deferedFree) {
+-                                      yaffs_ObjectToCheckpointObject(&cp,obj);
+-                                      cp.structType = sizeof(cp);
++         */
++         
++         for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
++                ylist_for_each(lh, &dev->objectBucket[i].list) {
++                        if (lh) {
++                                obj = ylist_entry(lh, yaffs_Object, hashLink);
++                                if (!obj->deferedFree) {
++                                        yaffs_ObjectToCheckpointObject(&cp,obj);
++                                        cp.structType = sizeof(cp);
+                                       T(YAFFS_TRACE_CHECKPOINT,(
+                                               TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
+-                                              cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
++                                              cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk,(unsigned) obj));
+                                       ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
+-
++                                      
+                                       if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
+                                               ok = yaffs_WriteCheckpointTnodes(obj);
+                                       }
+@@ -4343,14 +4480,14 @@ static int yaffs_WriteCheckpointObjects(
+                       }
+               }
+        }
+-
++       
+        /* Dump end of list */
+       memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
+       cp.structType = sizeof(cp);
+-
++      
+       if(ok)
+               ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
+-
++              
+       return ok ? 1 : 0;
+ }
+@@ -4361,7 +4498,7 @@ static int yaffs_ReadCheckpointObjects(y
+       int ok = 1;
+       int done = 0;
+       yaffs_Object *hardList = NULL;
+-
++      
+       while(ok && !done) {
+               ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
+               if(cp.structType != sizeof(cp)) {
+@@ -4369,9 +4506,9 @@ static int yaffs_ReadCheckpointObjects(y
+                               cp.structType,sizeof(cp),ok));
+                       ok = 0;
+               }
+-
++                      
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
+-                      cp.objectId,cp.parentId,cp.variantType,cp.chunkId));
++                      cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk));
+               if(ok && cp.objectId == ~0)
+                       done = 1;
+@@ -4380,21 +4517,21 @@ static int yaffs_ReadCheckpointObjects(y
+                       if(obj) {
+                               yaffs_CheckpointObjectToObject(obj,&cp);
+                               if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
+-                                      ok = yaffs_ReadCheckpointTnodes(obj);
+-                              } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
+-                                      obj->hardLinks.next =
+-                                                  (struct list_head *)
+-                                                  hardList;
+-                                      hardList = obj;
+-                              }
+-
++                                        ok = yaffs_ReadCheckpointTnodes(obj);
++                                } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
++                                        obj->hardLinks.next =
++                                                    (struct ylist_head *)
++                                                    hardList;
++                                        hardList = obj;
++                                }
++                         
+                       }
+               }
+       }
+-
++      
+       if(ok)
+               yaffs_HardlinkFixup(dev,hardList);
+-
++      
+       return ok ? 1 : 0;
+ }
+@@ -4402,14 +4539,14 @@ static int yaffs_WriteCheckpointSum(yaff
+ {
+       __u32 checkpointSum;
+       int ok;
+-
++      
+       yaffs_GetCheckpointSum(dev,&checkpointSum);
+-
++      
+       ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum));
+-
++      
+       if(!ok)
+               return 0;
+-
++      
+       return 1;
+ }
+@@ -4418,17 +4555,17 @@ static int yaffs_ReadCheckpointSum(yaffs
+       __u32 checkpointSum0;
+       __u32 checkpointSum1;
+       int ok;
+-
++      
+       yaffs_GetCheckpointSum(dev,&checkpointSum0);
+-
++      
+       ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1));
+-
++      
+       if(!ok)
+               return 0;
+-
++              
+       if(checkpointSum0 != checkpointSum1)
+               return 0;
+-
++      
+       return 1;
+ }
+@@ -4437,15 +4574,15 @@ static int yaffs_WriteCheckpointData(yaf
+ {
+       int ok = 1;
+-
++      
+       if(dev->skipCheckpointWrite || !dev->isYaffs2){
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR)));
+               ok = 0;
+       }
+-
++              
+       if(ok)
+               ok = yaffs_CheckpointOpen(dev,1);
+-
++      
+       if(ok){
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
+               ok = yaffs_WriteCheckpointValidityMarker(dev,1);
+@@ -4462,18 +4599,18 @@ static int yaffs_WriteCheckpointData(yaf
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
+               ok = yaffs_WriteCheckpointValidityMarker(dev,0);
+       }
+-
++      
+       if(ok){
+               ok = yaffs_WriteCheckpointSum(dev);
+       }
+-
+-
++      
++      
+       if(!yaffs_CheckpointClose(dev))
+                ok = 0;
+-
++               
+       if(ok)
+               dev->isCheckpointed = 1;
+-       else
++       else 
+               dev->isCheckpointed = 0;
+       return dev->isCheckpointed;
+@@ -4482,17 +4619,17 @@ static int yaffs_WriteCheckpointData(yaf
+ static int yaffs_ReadCheckpointData(yaffs_Device *dev)
+ {
+       int ok = 1;
+-
++      
+       if(dev->skipCheckpointRead || !dev->isYaffs2){
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR)));
+               ok = 0;
+       }
+-
++      
+       if(ok)
+               ok = yaffs_CheckpointOpen(dev,0); /* open for read */
+-
++      
+       if(ok){
+-              T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
++              T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));   
+               ok = yaffs_ReadCheckpointValidityMarker(dev,1);
+       }
+       if(ok){
+@@ -4500,14 +4637,14 @@ static int yaffs_ReadCheckpointData(yaff
+               ok = yaffs_ReadCheckpointDevice(dev);
+       }
+       if(ok){
+-              T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
++              T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));    
+               ok = yaffs_ReadCheckpointObjects(dev);
+       }
+       if(ok){
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
+               ok = yaffs_ReadCheckpointValidityMarker(dev,0);
+       }
+-
++      
+       if(ok){
+               ok = yaffs_ReadCheckpointSum(dev);
+               T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok));
+@@ -4518,7 +4655,7 @@ static int yaffs_ReadCheckpointData(yaff
+       if(ok)
+               dev->isCheckpointed = 1;
+-       else
++       else 
+               dev->isCheckpointed = 0;
+       return ok ? 1 : 0;
+@@ -4527,7 +4664,7 @@ static int yaffs_ReadCheckpointData(yaff
+ static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
+ {
+-      if(dev->isCheckpointed ||
++      if(dev->isCheckpointed || 
+          dev->blocksInCheckpoint > 0){
+               dev->isCheckpointed = 0;
+               yaffs_CheckpointInvalidateStream(dev);
+@@ -4550,7 +4687,7 @@ int yaffs_CheckpointSave(yaffs_Device *d
+               yaffs_InvalidateCheckpoint(dev);
+               yaffs_WriteCheckpointData(dev);
+       }
+-
++      
+       T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+       return dev->isCheckpointed;
+@@ -4560,7 +4697,7 @@ int yaffs_CheckpointRestore(yaffs_Device
+ {
+       int retval;
+       T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+-
++              
+       retval = yaffs_ReadCheckpointData(dev);
+       if(dev->isCheckpointed){
+@@ -4570,7 +4707,7 @@ int yaffs_CheckpointRestore(yaffs_Device
+       }
+       T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
+-
++      
+       return retval;
+ }
+@@ -4589,7 +4726,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
+ {
+       int chunk;
+-      int start;
++      __u32 start;
+       int nToCopy;
+       int n = nBytes;
+       int nDone = 0;
+@@ -4606,7 +4743,7 @@ int yaffs_ReadDataFromFile(yaffs_Object 
+               chunk++;
+               /* OK now check for the curveball where the start and end are in
+-               * the same chunk.
++               * the same chunk.      
+                */
+               if ((start + n) < dev->nDataBytesPerChunk) {
+                       nToCopy = n;
+@@ -4617,10 +4754,10 @@ int yaffs_ReadDataFromFile(yaffs_Object 
+               cache = yaffs_FindChunkCache(in, chunk);
+               /* If the chunk is already in the cache or it is less than a whole chunk
+-               * then use the cache (if there is caching)
++               * or we're using inband tags then use the cache (if there is caching)
+                * else bypass the cache.
+                */
+-              if (cache || nToCopy != dev->nDataBytesPerChunk) {
++              if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
+                       if (dev->nShortOpCaches > 0) {
+                               /* If we can't find the data in the cache, then load it up. */
+@@ -4641,14 +4778,9 @@ int yaffs_ReadDataFromFile(yaffs_Object 
+                               cache->locked = 1;
+-#ifdef CONFIG_YAFFS_WINCE
+-                              yfsd_UnlockYAFFS(TRUE);
+-#endif
++
+                               memcpy(buffer, &cache->data[start], nToCopy);
+-#ifdef CONFIG_YAFFS_WINCE
+-                              yfsd_LockYAFFS(TRUE);
+-#endif
+                               cache->locked = 0;
+                       } else {
+                               /* Read into the local buffer then copy..*/
+@@ -4657,41 +4789,19 @@ int yaffs_ReadDataFromFile(yaffs_Object 
+                                   yaffs_GetTempBuffer(dev, __LINE__);
+                               yaffs_ReadChunkDataFromObject(in, chunk,
+                                                             localBuffer);
+-#ifdef CONFIG_YAFFS_WINCE
+-                              yfsd_UnlockYAFFS(TRUE);
+-#endif
++
+                               memcpy(buffer, &localBuffer[start], nToCopy);
+-#ifdef CONFIG_YAFFS_WINCE
+-                              yfsd_LockYAFFS(TRUE);
+-#endif
++
+                               yaffs_ReleaseTempBuffer(dev, localBuffer,
+                                                       __LINE__);
+                       }
+               } else {
+-#ifdef CONFIG_YAFFS_WINCE
+-                      __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
+-
+-                      /* Under WinCE can't do direct transfer. Need to use a local buffer.
+-                       * This is because we otherwise screw up WinCE's memory mapper
+-                       */
+-                      yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
+-
+-#ifdef CONFIG_YAFFS_WINCE
+-                      yfsd_UnlockYAFFS(TRUE);
+-#endif
+-                      memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
+-#ifdef CONFIG_YAFFS_WINCE
+-                      yfsd_LockYAFFS(TRUE);
+-                      yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
+-#endif
+-
+-#else
+                       /* A full chunk. Read directly into the supplied buffer. */
+                       yaffs_ReadChunkDataFromObject(in, chunk, buffer);
+-#endif
++
+               }
+               n -= nToCopy;
+@@ -4709,14 +4819,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
+ {
+       int chunk;
+-      int start;
++      __u32 start;
+       int nToCopy;
+-      int n = nBytes;
+-      int nDone = 0;
+-      int nToWriteBack;
+-      int startOfWrite = offset;
+-      int chunkWritten = 0;
+-      int nBytesRead;
++        int n = nBytes;
++        int nDone = 0;
++        int nToWriteBack;
++        int startOfWrite = offset;
++        int chunkWritten = 0;
++        __u32 nBytesRead;
++        __u32 chunkStart;
+       yaffs_Device *dev;
+@@ -4726,6 +4837,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
+               //chunk = offset / dev->nDataBytesPerChunk + 1;
+               //start = offset % dev->nDataBytesPerChunk;
+               yaffs_AddrToChunk(dev,offset,&chunk,&start);
++              
++              if(chunk * dev->nDataBytesPerChunk + start != offset ||
++                 start >= dev->nDataBytesPerChunk){
++                 T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
++                                      (int)offset, chunk,start));
++              }
+               chunk++;
+               /* OK now check for the curveball where the start and end are in
+@@ -4740,9 +4857,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
+                        * we need to write back as much as was there before.
+                        */
+-                      nBytesRead =
+-                          in->variant.fileVariant.fileSize -
+-                          ((chunk - 1) * dev->nDataBytesPerChunk);
++                      chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk);
++
++                      if(chunkStart > in->variant.fileVariant.fileSize)
++                              nBytesRead = 0; /* Past end of file */
++                      else
++                              nBytesRead = in->variant.fileVariant.fileSize - chunkStart;
+                       if (nBytesRead > dev->nDataBytesPerChunk) {
+                               nBytesRead = dev->nDataBytesPerChunk;
+@@ -4751,19 +4871,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
+                       nToWriteBack =
+                           (nBytesRead >
+                            (start + n)) ? nBytesRead : (start + n);
++                      
++                      if(nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk)
++                              YBUG();
+               } else {
+                       nToCopy = dev->nDataBytesPerChunk - start;
+                       nToWriteBack = dev->nDataBytesPerChunk;
+               }
+-              if (nToCopy != dev->nDataBytesPerChunk) {
+-                      /* An incomplete start or end chunk (or maybe both start and end chunk) */
++              if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
++                      /* An incomplete start or end chunk (or maybe both start and end chunk), 
++                       * or we're using inband tags, so we want to use the cache buffers.
++                       */
+                       if (dev->nShortOpCaches > 0) {
+                               yaffs_ChunkCache *cache;
+                               /* If we can't find the data in the cache, then load the cache */
+                               cache = yaffs_FindChunkCache(in, chunk);
+-
++                              
+                               if (!cache
+                                   && yaffs_CheckSpaceForAllocation(in->
+                                                                    myDev)) {
+@@ -4776,28 +4901,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
+                                                                     cache->
+                                                                     data);
+                               }
+-                              else if(cache &&
++                              else if(cache && 
+                                       !cache->dirty &&
+                                       !yaffs_CheckSpaceForAllocation(in->myDev)){
+                                       /* Drop the cache if it was a read cache item and
+                                        * no space check has been made for it.
+-                                       */
++                                       */ 
+                                        cache = NULL;
+                               }
+                               if (cache) {
+                                       yaffs_UseChunkCache(dev, cache, 1);
+                                       cache->locked = 1;
+-#ifdef CONFIG_YAFFS_WINCE
+-                                      yfsd_UnlockYAFFS(TRUE);
+-#endif
++
+                                       memcpy(&cache->data[start], buffer,
+                                              nToCopy);
+-#ifdef CONFIG_YAFFS_WINCE
+-                                      yfsd_LockYAFFS(TRUE);
+-#endif
++
+                                       cache->locked = 0;
+                                       cache->nBytes = nToWriteBack;
+@@ -4825,15 +4946,10 @@ int yaffs_WriteDataToFile(yaffs_Object *
+                               yaffs_ReadChunkDataFromObject(in, chunk,
+                                                             localBuffer);
+-#ifdef CONFIG_YAFFS_WINCE
+-                              yfsd_UnlockYAFFS(TRUE);
+-#endif
++
+                               memcpy(&localBuffer[start], buffer, nToCopy);
+-#ifdef CONFIG_YAFFS_WINCE
+-                              yfsd_LockYAFFS(TRUE);
+-#endif
+                               chunkWritten =
+                                   yaffs_WriteChunkDataToObject(in, chunk,
+                                                                localBuffer,
+@@ -4846,31 +4962,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
+                       }
+               } else {
+-
+-#ifdef CONFIG_YAFFS_WINCE
+-                      /* Under WinCE can't do direct transfer. Need to use a local buffer.
+-                       * This is because we otherwise screw up WinCE's memory mapper
+-                       */
+-                      __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
+-#ifdef CONFIG_YAFFS_WINCE
+-                      yfsd_UnlockYAFFS(TRUE);
+-#endif
+-                      memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
+-#ifdef CONFIG_YAFFS_WINCE
+-                      yfsd_LockYAFFS(TRUE);
+-#endif
+-                      chunkWritten =
+-                          yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
+-                                                       dev->nDataBytesPerChunk,
+-                                                       0);
+-                      yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
+-#else
+                       /* A full chunk. Write directly from the supplied buffer. */
++                      
++
++
+                       chunkWritten =
+                           yaffs_WriteChunkDataToObject(in, chunk, buffer,
+                                                        dev->nDataBytesPerChunk,
+                                                        0);
+-#endif
++
+                       /* Since we've overwritten the cached data, we better invalidate it. */
+                       yaffs_InvalidateChunkCache(in, chunk);
+               }
+@@ -4943,9 +5043,9 @@ int yaffs_ResizeFile(yaffs_Object * in, 
+ {
+       int oldFileSize = in->variant.fileVariant.fileSize;
+-      int newSizeOfPartialChunk;
++      __u32 newSizeOfPartialChunk;
+       int newFullChunks;
+-
++      
+       yaffs_Device *dev = in->myDev;
+       yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
+@@ -4953,23 +5053,23 @@ int yaffs_ResizeFile(yaffs_Object * in, 
+       yaffs_FlushFilesChunkCache(in);
+       yaffs_InvalidateWholeChunkCache(in);
+-      yaffs_CheckGarbageCollection(dev);
++        yaffs_CheckGarbageCollection(dev);
+-      if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
+-              return yaffs_GetFileSize(in);
+-      }
++        if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
++                return YAFFS_FAIL;
++        }
+-      if (newSize == oldFileSize) {
+-              return oldFileSize;
+-      }
++        if (newSize == oldFileSize) {
++                return YAFFS_OK;
++        }
+-      if (newSize < oldFileSize) {
++        if (newSize < oldFileSize) {
+               yaffs_PruneResizedChunks(in, newSize);
+               if (newSizeOfPartialChunk != 0) {
+                       int lastChunk = 1 + newFullChunks;
+-
++                      
+                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
+                       /* Got to read and rewrite the last chunk with its new size and zero pad */
+@@ -4993,19 +5093,20 @@ int yaffs_ResizeFile(yaffs_Object * in, 
+               in->variant.fileVariant.fileSize = newSize;
+       }
+-
+-
++              
++      
+       /* Write a new object header.
+        * show we've shrunk the file, if need be
+        * Do this only if the file is not in the deleted directories.
+        */
+-      if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
++      if (in->parent &&
++          in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
+           in->parent->objectId != YAFFS_OBJECTID_DELETED) {
+               yaffs_UpdateObjectHeader(in, NULL, 0,
+                                        (newSize < oldFileSize) ? 1 : 0, 0);
+       }
+-      return newSize;
++      return YAFFS_OK;
+ }
+ loff_t yaffs_GetFileSize(yaffs_Object * obj)
+@@ -5058,13 +5159,13 @@ static int yaffs_DoGenericObjectDeletion
+       if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
+               /* Move to the unlinked directory so we have a record that it was deleted. */
+-              yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
++              yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
+       }
+       yaffs_RemoveObjectFromDirectory(in);
+-      yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
+-      in->chunkId = -1;
++      yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__);
++      in->hdrChunk = 0;
+       yaffs_FreeObject(in);
+       return YAFFS_OK;
+@@ -5075,62 +5176,66 @@ static int yaffs_DoGenericObjectDeletion
+  * and the inode associated with the file.
+  * It does not delete the links associated with the file.
+  */
++ 
+ static int yaffs_UnlinkFile(yaffs_Object * in)
+ {
+       int retVal;
+       int immediateDeletion = 0;
+-      if (1) {
+ #ifdef __KERNEL__
+-              if (!in->myInode) {
+-                      immediateDeletion = 1;
+-
+-              }
++      if (!in->myInode) {
++              immediateDeletion = 1;
++      }
+ #else
+-              if (in->inUse <= 0) {
+-                      immediateDeletion = 1;
+-
+-              }
++      if (in->inUse <= 0) {
++              immediateDeletion = 1;
++      }
+ #endif
+-              if (immediateDeletion) {
+-                      retVal =
+-                          yaffs_ChangeObjectName(in, in->myDev->deletedDir,
+-                                                 "deleted", 0, 0);
+-                      T(YAFFS_TRACE_TRACING,
+-                        (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
+-                         in->objectId));
+-                      in->deleted = 1;
+-                      in->myDev->nDeletedFiles++;
+-                      if (0 && in->myDev->isYaffs2) {
+-                              yaffs_ResizeFile(in, 0);
+-                      }
+-                      yaffs_SoftDeleteFile(in);
+-              } else {
+-                      retVal =
+-                          yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
+-                                                 "unlinked", 0, 0);
+-              }
++      if (immediateDeletion) {
++              retVal =
++                  yaffs_ChangeObjectName(in, in->myDev->deletedDir,
++                                         _Y("deleted"), 0, 0);
++              T(YAFFS_TRACE_TRACING,
++                (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
++                 in->objectId));
++              in->deleted = 1;
++              in->myDev->nDeletedFiles++;
++              if (1 || in->myDev->isYaffs2) {
++                      yaffs_ResizeFile(in, 0);
++              }
++              yaffs_SoftDeleteFile(in);
++      } else {
++              retVal =
++                  yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
++                                         _Y("unlinked"), 0, 0);
+       }
++
++
+       return retVal;
+ }
+ int yaffs_DeleteFile(yaffs_Object * in)
+ {
+       int retVal = YAFFS_OK;
++      int deleted = in->deleted;
++      
++      yaffs_ResizeFile(in,0);
+       if (in->nDataChunks > 0) {
+-              /* Use soft deletion if there is data in the file */
++              /* Use soft deletion if there is data in the file.
++               * That won't be the case if it has been resized to zero.
++               */
+               if (!in->unlinked) {
+                       retVal = yaffs_UnlinkFile(in);
+               }
+               if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
+-                      in->deleted = 1;
++                      in->deleted = deleted = 1;
+                       in->myDev->nDeletedFiles++;
+                       yaffs_SoftDeleteFile(in);
+               }
+-              return in->deleted ? YAFFS_OK : YAFFS_FAIL;
++              return deleted ? YAFFS_OK : YAFFS_FAIL;
+       } else {
+               /* The file has no data chunks so we toss it immediately */
+               yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
+@@ -5143,10 +5248,10 @@ int yaffs_DeleteFile(yaffs_Object * in)
+ static int yaffs_DeleteDirectory(yaffs_Object * in)
+ {
+-      /* First check that the directory is empty. */
+-      if (list_empty(&in->variant.directoryVariant.children)) {
+-              return yaffs_DoGenericObjectDeletion(in);
+-      }
++        /* First check that the directory is empty. */
++        if (ylist_empty(&in->variant.directoryVariant.children)) {
++                return yaffs_DoGenericObjectDeletion(in);
++        }
+       return YAFFS_FAIL;
+@@ -5161,11 +5266,11 @@ static int yaffs_DeleteSymLink(yaffs_Obj
+ static int yaffs_DeleteHardLink(yaffs_Object * in)
+ {
+-      /* remove this hardlink from the list assocaited with the equivalent
+-       * object
+-       */
+-      list_del(&in->hardLinks);
+-      return yaffs_DoGenericObjectDeletion(in);
++        /* remove this hardlink from the list assocaited with the equivalent
++         * object
++         */
++        ylist_del_init(&in->hardLinks);
++        return yaffs_DoGenericObjectDeletion(in);
+ }
+ static void yaffs_DestroyObject(yaffs_Object * obj)
+@@ -5194,12 +5299,12 @@ static void yaffs_DestroyObject(yaffs_Ob
+ static int yaffs_UnlinkWorker(yaffs_Object * obj)
+ {
+-      if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
+-              return yaffs_DeleteHardLink(obj);
+-      } else if (!list_empty(&obj->hardLinks)) {
+-              /* Curve ball: We're unlinking an object that has a hardlink.
+-               *
+-               * This problem arises because we are not strictly following
++        if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
++                return yaffs_DeleteHardLink(obj);
++        } else if (!ylist_empty(&obj->hardLinks)) {
++                /* Curve ball: We're unlinking an object that has a hardlink.
++                 *
++                 * This problem arises because we are not strictly following
+                * The Linux link/inode model.
+                *
+                * We can't really delete the object.
+@@ -5212,15 +5317,15 @@ static int yaffs_UnlinkWorker(yaffs_Obje
+                */
+               yaffs_Object *hl;
+-              int retVal;
+-              YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
++                int retVal;
++                YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
+-              hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
++                hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
+-              list_del_init(&hl->hardLinks);
+-              list_del_init(&hl->siblings);
++                ylist_del_init(&hl->hardLinks);
++                ylist_del_init(&hl->siblings);
+-              yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
++                yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
+               retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
+@@ -5313,7 +5418,7 @@ static void yaffs_HardlinkFixup(yaffs_De
+ {
+       yaffs_Object *hl;
+       yaffs_Object *in;
+-
++      
+       while (hardList) {
+               hl = hardList;
+               hardList = (yaffs_Object *) (hardList->hardLinks.next);
+@@ -5322,18 +5427,18 @@ static void yaffs_HardlinkFixup(yaffs_De
+                                             hl->variant.hardLinkVariant.
+                                             equivalentObjectId);
+-              if (in) {
+-                      /* Add the hardlink pointers */
+-                      hl->variant.hardLinkVariant.equivalentObject = in;
+-                      list_add(&hl->hardLinks, &in->hardLinks);
+-              } else {
+-                      /* Todo Need to report/handle this better.
+-                       * Got a problem... hardlink to a non-existant object
+-                       */
+-                      hl->variant.hardLinkVariant.equivalentObject = NULL;
+-                      INIT_LIST_HEAD(&hl->hardLinks);
++                if (in) {
++                        /* Add the hardlink pointers */
++                        hl->variant.hardLinkVariant.equivalentObject = in;
++                        ylist_add(&hl->hardLinks, &in->hardLinks);
++                } else {
++                        /* Todo Need to report/handle this better.
++                         * Got a problem... hardlink to a non-existant object
++                         */
++                        hl->variant.hardLinkVariant.equivalentObject = NULL;
++                        YINIT_LIST_HEAD(&hl->hardLinks);
+-              }
++                }
+       }
+@@ -5355,6 +5460,42 @@ static int ybicmp(const void *a, const v
+ }
++
++struct yaffs_ShadowFixerStruct {
++      int objectId;
++      int shadowedId;
++      struct yaffs_ShadowFixerStruct *next;
++};
++
++
++static void yaffs_StripDeletedObjects(yaffs_Device *dev)
++{
++      /*
++      *  Sort out state of unlinked and deleted objects after scanning.
++      */
++      struct ylist_head *i;
++      struct ylist_head *n;
++      yaffs_Object *l;
++
++      /* Soft delete all the unlinked files */
++      ylist_for_each_safe(i, n,
++              &dev->unlinkedDir->variant.directoryVariant.children) {
++              if (i) {
++                      l = ylist_entry(i, yaffs_Object, siblings);
++                      yaffs_DestroyObject(l);
++              }
++      }
++      
++      ylist_for_each_safe(i, n,
++              &dev->deletedDir->variant.directoryVariant.children) {
++              if (i) {
++                      l = ylist_entry(i, yaffs_Object, siblings);
++                      yaffs_DestroyObject(l);
++              }
++      }
++
++}
++
+ static int yaffs_Scan(yaffs_Device * dev)
+ {
+       yaffs_ExtendedTags tags;
+@@ -5362,7 +5503,6 @@ static int yaffs_Scan(yaffs_Device * dev
+       int blockIterator;
+       int startIterator;
+       int endIterator;
+-      int nBlocksToScan = 0;
+       int result;
+       int chunk;
+@@ -5371,27 +5511,20 @@ static int yaffs_Scan(yaffs_Device * dev
+       yaffs_BlockState state;
+       yaffs_Object *hardList = NULL;
+       yaffs_BlockInfo *bi;
+-      int sequenceNumber;
++      __u32 sequenceNumber;
+       yaffs_ObjectHeader *oh;
+       yaffs_Object *in;
+       yaffs_Object *parent;
+-      int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
+-
++      
+       int alloc_failed = 0;
+-
++      
++      struct yaffs_ShadowFixerStruct *shadowFixerList = NULL;
++      
+       __u8 *chunkData;
+-      yaffs_BlockIndex *blockIndex = NULL;
+-
+-      if (dev->isYaffs2) {
+-              T(YAFFS_TRACE_SCAN,
+-                (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
+-              return YAFFS_FAIL;
+-      }
+-
+-      //TODO  Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
+-
++      
++      
+       T(YAFFS_TRACE_SCAN,
+         (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
+          dev->internalStartBlock, dev->internalEndBlock));
+@@ -5400,12 +5533,6 @@ static int yaffs_Scan(yaffs_Device * dev
+       dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
+-      if (dev->isYaffs2) {
+-              blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
+-              if(!blockIndex)
+-                      return YAFFS_FAIL;
+-      }
+-
+       /* Scan all the blocks to determine their state */
+       for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
+               bi = yaffs_GetBlockInfo(dev, blk);
+@@ -5430,70 +5557,21 @@ static int yaffs_Scan(yaffs_Device * dev
+                         (TSTR("Block empty " TENDSTR)));
+                       dev->nErasedBlocks++;
+                       dev->nFreeChunks += dev->nChunksPerBlock;
+-              } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+-
+-                      /* Determine the highest sequence number */
+-                      if (dev->isYaffs2 &&
+-                          sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
+-                          sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
+-
+-                              blockIndex[nBlocksToScan].seq = sequenceNumber;
+-                              blockIndex[nBlocksToScan].block = blk;
+-
+-                              nBlocksToScan++;
+-
+-                              if (sequenceNumber >= dev->sequenceNumber) {
+-                                      dev->sequenceNumber = sequenceNumber;
+-                              }
+-                      } else if (dev->isYaffs2) {
+-                              /* TODO: Nasty sequence number! */
+-                              T(YAFFS_TRACE_SCAN,
+-                                (TSTR
+-                                 ("Block scanning block %d has bad sequence number %d"
+-                                  TENDSTR), blk, sequenceNumber));
+-
+-                      }
+-              }
++              } 
+       }
+-      /* Sort the blocks
+-       * Dungy old bubble sort for now...
+-       */
+-      if (dev->isYaffs2) {
+-              yaffs_BlockIndex temp;
+-              int i;
+-              int j;
+-
+-              for (i = 0; i < nBlocksToScan; i++)
+-                      for (j = i + 1; j < nBlocksToScan; j++)
+-                              if (blockIndex[i].seq > blockIndex[j].seq) {
+-                                      temp = blockIndex[j];
+-                                      blockIndex[j] = blockIndex[i];
+-                                      blockIndex[i] = temp;
+-                              }
+-      }
+-
+-      /* Now scan the blocks looking at the data. */
+-      if (dev->isYaffs2) {
+-              startIterator = 0;
+-              endIterator = nBlocksToScan - 1;
+-              T(YAFFS_TRACE_SCAN_DEBUG,
+-                (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
+-      } else {
+-              startIterator = dev->internalStartBlock;
+-              endIterator = dev->internalEndBlock;
+-      }
++      startIterator = dev->internalStartBlock;
++      endIterator = dev->internalEndBlock;
+       /* For each block.... */
+       for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
+            blockIterator++) {
++              
++              YYIELD();
+-              if (dev->isYaffs2) {
+-                      /* get the block to scan in the correct order */
+-                      blk = blockIndex[blockIterator].block;
+-              } else {
+-                      blk = blockIterator;
+-              }
++              YYIELD();
++              
++              blk = blockIterator;
+               bi = yaffs_GetBlockInfo(dev, blk);
+               state = bi->blockState;
+@@ -5511,7 +5589,7 @@ static int yaffs_Scan(yaffs_Device * dev
+                       /* Let's have a good look at this chunk... */
+-                      if (!dev->isYaffs2 && tags.chunkDeleted) {
++                      if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {
+                               /* YAFFS1 only...
+                                * A deleted chunk
+                                */
+@@ -5520,7 +5598,7 @@ static int yaffs_Scan(yaffs_Device * dev
+                               /*T((" %d %d deleted\n",blk,c)); */
+                       } else if (!tags.chunkUsed) {
+                               /* An unassigned chunk in the block
+-                               * This means that either the block is empty or
++                               * This means that either the block is empty or 
+                                * this is the one being allocated from
+                                */
+@@ -5537,21 +5615,9 @@ static int yaffs_Scan(yaffs_Device * dev
+                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
+                                       dev->allocationBlock = blk;
+                                       dev->allocationPage = c;
+-                                      dev->allocationBlockFinder = blk;
++                                      dev->allocationBlockFinder = blk;       
+                                       /* Set it to here to encourage the allocator to go forth from here. */
+-
+-                                      /* Yaffs2 sanity check:
+-                                       * This should be the one with the highest sequence number
+-                                       */
+-                                      if (dev->isYaffs2
+-                                          && (dev->sequenceNumber !=
+-                                              bi->sequenceNumber)) {
+-                                              T(YAFFS_TRACE_ALWAYS,
+-                                                (TSTR
+-                                                 ("yaffs: Allocation block %d was not highest sequence id:"
+-                                                  " block seq = %d, dev seq = %d"
+-                                                  TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
+-                                      }
++                                      
+                               }
+                               dev->nFreeChunks += (dev->nChunksPerBlock - c);
+@@ -5569,7 +5635,7 @@ static int yaffs_Scan(yaffs_Device * dev
+                               /* PutChunkIntoFile checks for a clash (two data chunks with
+                                * the same chunkId).
+                                */
+-
++                               
+                               if(!in)
+                                       alloc_failed = 1;
+@@ -5577,11 +5643,11 @@ static int yaffs_Scan(yaffs_Device * dev
+                                       if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1))
+                                               alloc_failed = 1;
+                               }
+-
++                              
+                               endpos =
+                                   (tags.chunkId - 1) * dev->nDataBytesPerChunk +
+                                   tags.byteCount;
+-                              if (in &&
++                              if (in && 
+                                   in->variantType == YAFFS_OBJECT_TYPE_FILE
+                                   && in->variant.fileVariant.scannedFileSize <
+                                   endpos) {
+@@ -5613,7 +5679,7 @@ static int yaffs_Scan(yaffs_Device * dev
+                                                             tags.objectId);
+                               if (in && in->variantType != oh->type) {
+                                       /* This should not happen, but somehow
+-                                       * Wev'e ended up with an objectId that has been reused but not yet
++                                       * Wev'e ended up with an objectId that has been reused but not yet 
+                                        * deleted, and worse still it has changed type. Delete the old object.
+                                        */
+@@ -5629,12 +5695,18 @@ static int yaffs_Scan(yaffs_Device * dev
+                               if(!in)
+                                       alloc_failed = 1;
+-
++                                      
+                               if (in && oh->shadowsObject > 0) {
+-                                      yaffs_HandleShadowedObject(dev,
+-                                                                 oh->
+-                                                                 shadowsObject,
+-                                                                 0);
++                              
++                                      struct yaffs_ShadowFixerStruct *fixer;
++                                      fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct));
++                                      if(fixer){
++                                              fixer-> next = shadowFixerList;
++                                              shadowFixerList = fixer;
++                                              fixer->objectId = tags.objectId;
++                                              fixer->shadowedId = oh->shadowsObject;
++                                      }
++                                      
+                               }
+                               if (in && in->valid) {
+@@ -5643,12 +5715,10 @@ static int yaffs_Scan(yaffs_Device * dev
+                                       unsigned existingSerial = in->serial;
+                                       unsigned newSerial = tags.serialNumber;
+-                                      if (dev->isYaffs2 ||
+-                                          ((existingSerial + 1) & 3) ==
+-                                          newSerial) {
++                                      if (((existingSerial + 1) & 3) == newSerial) {
+                                               /* Use new one - destroy the exisiting one */
+                                               yaffs_DeleteChunk(dev,
+-                                                                in->chunkId,
++                                                                in->hdrChunk,
+                                                                 1, __LINE__);
+                                               in->valid = 0;
+                                       } else {
+@@ -5681,7 +5751,8 @@ static int yaffs_Scan(yaffs_Device * dev
+                                       in->yst_ctime = oh->yst_ctime;
+                                       in->yst_rdev = oh->yst_rdev;
+ #endif
+-                                      in->chunkId = chunk;
++                                      in->hdrChunk = chunk;
++                                      in->serial = tags.serialNumber;
+                               } else if (in && !in->valid) {
+                                       /* we need to load this info */
+@@ -5705,7 +5776,8 @@ static int yaffs_Scan(yaffs_Device * dev
+                                       in->yst_ctime = oh->yst_ctime;
+                                       in->yst_rdev = oh->yst_rdev;
+ #endif
+-                                      in->chunkId = chunk;
++                                      in->hdrChunk = chunk;
++                                      in->serial = tags.serialNumber;
+                                       yaffs_SetObjectName(in, oh->name);
+                                       in->dirty = 0;
+@@ -5720,13 +5792,13 @@ static int yaffs_Scan(yaffs_Device * dev
+                                            YAFFS_OBJECT_TYPE_DIRECTORY);
+                                       if (parent->variantType ==
+                                           YAFFS_OBJECT_TYPE_UNKNOWN) {
+-                                              /* Set up as a directory */
+-                                              parent->variantType =
+-                                                  YAFFS_OBJECT_TYPE_DIRECTORY;
+-                                              INIT_LIST_HEAD(&parent->variant.
+-                                                             directoryVariant.
+-                                                             children);
+-                                      } else if (parent->variantType !=
++                                                /* Set up as a directory */
++                                                parent->variantType =
++                                                    YAFFS_OBJECT_TYPE_DIRECTORY;
++                                                YINIT_LIST_HEAD(&parent->variant.
++                                                               directoryVariant.
++                                                               children);
++                                        } else if (parent->variantType !=
+                                                  YAFFS_OBJECT_TYPE_DIRECTORY)
+                                       {
+                                               /* Hoosterman, another problem....
+@@ -5735,8 +5807,7 @@ static int yaffs_Scan(yaffs_Device * dev
+                                               T(YAFFS_TRACE_ERROR,
+                                                 (TSTR
+-                                                 ("yaffs tragedy: attempting to use non-directory as"
+-                                                  " a directory in scan. Put in lost+found."
++                                                 ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
+                                                   TENDSTR)));
+                                               parent = dev->lostNFoundDir;
+                                       }
+@@ -5752,23 +5823,14 @@ static int yaffs_Scan(yaffs_Device * dev
+                                        * Since we might scan a hardlink before its equivalent object is scanned
+                                        * we put them all in a list.
+                                        * After scanning is complete, we should have all the objects, so we run through this
+-                                       * list and fix up all the chains.
++                                       * list and fix up all the chains.              
+                                        */
+                                       switch (in->variantType) {
+-                                      case YAFFS_OBJECT_TYPE_UNKNOWN:
++                                      case YAFFS_OBJECT_TYPE_UNKNOWN: 
+                                               /* Todo got a problem */
+                                               break;
+                                       case YAFFS_OBJECT_TYPE_FILE:
+-                                              if (dev->isYaffs2
+-                                                  && oh->isShrink) {
+-                                                      /* Prune back the shrunken chunks */
+-                                                      yaffs_PruneResizedChunks
+-                                                          (in, oh->fileSize);
+-                                                      /* Mark the block as having a shrinkHeader */
+-                                                      bi->hasShrinkHeader = 1;
+-                                              }
+-
+                                               if (dev->useHeaderFileSize)
+                                                       in->variant.fileVariant.
+@@ -5778,20 +5840,20 @@ static int yaffs_Scan(yaffs_Device * dev
+                                               break;
+                                       case YAFFS_OBJECT_TYPE_HARDLINK:
+                                               in->variant.hardLinkVariant.
+-                                                  equivalentObjectId =
+-                                                  oh->equivalentObjectId;
+-                                              in->hardLinks.next =
+-                                                  (struct list_head *)
+-                                                  hardList;
+-                                              hardList = in;
+-                                              break;
++                                                    equivalentObjectId =
++                                                    oh->equivalentObjectId;
++                                                in->hardLinks.next =
++                                                    (struct ylist_head *)
++                                                    hardList;
++                                                hardList = in;
++                                                break;
+                                       case YAFFS_OBJECT_TYPE_DIRECTORY:
+                                               /* Do nothing */
+                                               break;
+                                       case YAFFS_OBJECT_TYPE_SPECIAL:
+                                               /* Do nothing */
+                                               break;
+-                                      case YAFFS_OBJECT_TYPE_SYMLINK:
++                                      case YAFFS_OBJECT_TYPE_SYMLINK: 
+                                               in->variant.symLinkVariant.alias =
+                                                   yaffs_CloneString(oh->alias);
+                                               if(!in->variant.symLinkVariant.alias)
+@@ -5799,10 +5861,12 @@ static int yaffs_Scan(yaffs_Device * dev
+                                               break;
+                                       }
+-                                      if (parent == dev->deletedDir) {
++/*
++                                      if (parent == dev->deletedDir) {
+                                               yaffs_DestroyObject(in);
+                                               bi->hasShrinkHeader = 1;
+                                       }
++*/
+                               }
+                       }
+               }
+@@ -5823,35 +5887,36 @@ static int yaffs_Scan(yaffs_Device * dev
+       }
+-      if (blockIndex) {
+-              YFREE(blockIndex);
+-      }
+-
+-
++      
+       /* Ok, we've done all the scanning.
+        * Fix up the hard link chains.
+-       * We should now have scanned all the objects, now it's time to add these
++       * We should now have scanned all the objects, now it's time to add these 
+        * hardlinks.
+        */
+       yaffs_HardlinkFixup(dev,hardList);
+-
+-      /* Handle the unlinked files. Since they were left in an unlinked state we should
+-       * just delete them.
+-       */
++      
++      /* Fix up any shadowed objects */
+       {
+-              struct list_head *i;
+-              struct list_head *n;
+-
+-              yaffs_Object *l;
+-              /* Soft delete all the unlinked files */
+-              list_for_each_safe(i, n,
+-                                 &dev->unlinkedDir->variant.directoryVariant.
+-                                 children) {
+-                      if (i) {
+-                              l = list_entry(i, yaffs_Object, siblings);
+-                              yaffs_DestroyObject(l);
++              struct yaffs_ShadowFixerStruct *fixer;
++              yaffs_Object *obj;
++              
++              while(shadowFixerList){
++                      fixer = shadowFixerList;
++                      shadowFixerList = fixer->next;
++                      /* Complete the rename transaction by deleting the shadowed object
++                       * then setting the object header to unshadowed.
++                       */
++                      obj = yaffs_FindObjectByNumber(dev,fixer->shadowedId);
++                      if(obj)
++                              yaffs_DestroyObject(obj);
++      
++                      obj = yaffs_FindObjectByNumber(dev,fixer->objectId);
++                      if(obj){
++                              yaffs_UpdateObjectHeader(obj,NULL,1,0,0);
+                       }
++                      
++                      YFREE(fixer);
+               }
+       }
+@@ -5860,9 +5925,9 @@ static int yaffs_Scan(yaffs_Device * dev
+       if(alloc_failed){
+               return YAFFS_FAIL;
+       }
+-
++      
+       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
+-
++      
+       return YAFFS_OK;
+ }
+@@ -5871,25 +5936,27 @@ static void yaffs_CheckObjectDetailsLoad
+ {
+       __u8 *chunkData;
+       yaffs_ObjectHeader *oh;
+-      yaffs_Device *dev = in->myDev;
++      yaffs_Device *dev;
+       yaffs_ExtendedTags tags;
+       int result;
+       int alloc_failed = 0;
+       if(!in)
+               return;
+-
++              
++      dev = in->myDev;
++              
+ #if 0
+       T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
+               in->objectId,
+               in->lazyLoaded ? "not yet" : "already"));
+ #endif
+-      if(in->lazyLoaded){
++      if(in->lazyLoaded && in->hdrChunk > 0){
+               in->lazyLoaded = 0;
+               chunkData = yaffs_GetTempBuffer(dev, __LINE__);
+-              result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
++              result = yaffs_ReadChunkWithTagsFromNAND(dev,in->hdrChunk,chunkData,&tags);
+               oh = (yaffs_ObjectHeader *) chunkData;
+               in->yst_mode = oh->yst_mode;
+@@ -5907,17 +5974,17 @@ static void yaffs_CheckObjectDetailsLoad
+               in->yst_mtime = oh->yst_mtime;
+               in->yst_ctime = oh->yst_ctime;
+               in->yst_rdev = oh->yst_rdev;
+-
++              
+ #endif
+               yaffs_SetObjectName(in, oh->name);
+-
++              
+               if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){
+                        in->variant.symLinkVariant.alias =
+                                                   yaffs_CloneString(oh->alias);
+                       if(!in->variant.symLinkVariant.alias)
+                               alloc_failed = 1; /* Not returned to caller */
+               }
+-
++                                                  
+               yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
+       }
+ }
+@@ -5938,20 +6005,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
+       yaffs_BlockState state;
+       yaffs_Object *hardList = NULL;
+       yaffs_BlockInfo *bi;
+-      int sequenceNumber;
++      __u32 sequenceNumber;
+       yaffs_ObjectHeader *oh;
+       yaffs_Object *in;
+       yaffs_Object *parent;
+       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
+       int itsUnlinked;
+       __u8 *chunkData;
+-
++      
+       int fileSize;
+       int isShrink;
+       int foundChunksInBlock;
+       int equivalentObjectId;
+       int alloc_failed = 0;
+-
++      
+       yaffs_BlockIndex *blockIndex = NULL;
+       int altBlockIndex = 0;
+@@ -5971,20 +6038,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
+       dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
+       blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
+-
++      
+       if(!blockIndex) {
+               blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
+               altBlockIndex = 1;
+       }
+-
++      
+       if(!blockIndex) {
+               T(YAFFS_TRACE_SCAN,
+                 (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
+               return YAFFS_FAIL;
+       }
+-
++      
+       dev->blocksInCheckpoint = 0;
+-
++      
+       chunkData = yaffs_GetTempBuffer(dev, __LINE__);
+       /* Scan all the blocks to determine their state */
+@@ -6001,15 +6068,15 @@ static int yaffs_ScanBackwards(yaffs_Dev
+               if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
+                       bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
+-
++                      
+               T(YAFFS_TRACE_SCAN_DEBUG,
+                 (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
+                  state, sequenceNumber));
+-
++              
+               if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
+                       dev->blocksInCheckpoint++;
+-
++                      
+               } else if (state == YAFFS_BLOCK_STATE_DEAD) {
+                       T(YAFFS_TRACE_BAD_BLOCKS,
+                         (TSTR("block %d is bad" TENDSTR), blk));
+@@ -6021,8 +6088,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+               } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
+                       /* Determine the highest sequence number */
+-                      if (dev->isYaffs2 &&
+-                          sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
++                      if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
+                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
+                               blockIndex[nBlocksToScan].seq = sequenceNumber;
+@@ -6033,7 +6099,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                               if (sequenceNumber >= dev->sequenceNumber) {
+                                       dev->sequenceNumber = sequenceNumber;
+                               }
+-                      } else if (dev->isYaffs2) {
++                      } else {
+                               /* TODO: Nasty sequence number! */
+                               T(YAFFS_TRACE_SCAN,
+                                 (TSTR
+@@ -6053,12 +6119,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
+       /* Sort the blocks */
+ #ifndef CONFIG_YAFFS_USE_OWN_SORT
+-      yaffs_qsort(blockIndex, nBlocksToScan,
+-              sizeof(yaffs_BlockIndex), ybicmp);
++      {
++              /* Use qsort now. */
++              yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
++      }
+ #else
+       {
+               /* Dungy old bubble sort... */
+-
++              
+               yaffs_BlockIndex temp;
+               int i;
+               int j;
+@@ -6094,22 +6162,22 @@ static int yaffs_ScanBackwards(yaffs_Dev
+               blk = blockIndex[blockIterator].block;
+               bi = yaffs_GetBlockInfo(dev, blk);
+-
+-
++              
++              
+               state = bi->blockState;
+               deleted = 0;
+               /* For each chunk in each block that needs scanning.... */
+               foundChunksInBlock = 0;
+-              for (c = dev->nChunksPerBlock - 1;
++              for (c = dev->nChunksPerBlock - 1; 
+                    !alloc_failed && c >= 0 &&
+                    (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
+                     state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
+-                      /* Scan backwards...
++                      /* Scan backwards... 
+                        * Read the tags and decide what to do
+                        */
+-
++                      
+                       chunk = blk * dev->nChunksPerBlock + c;
+                       result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
+@@ -6123,14 +6191,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                * it is a chunk that was skipped due to failing the erased
+                                * check. Just skip it so that it can be deleted.
+                                * But, more typically, We get here when this is an unallocated
+-                               * chunk and his means that either the block is empty or
++                               * chunk and his means that either the block is empty or 
+                                * this is the one being allocated from
+                                */
+                               if(foundChunksInBlock)
+                               {
+                                       /* This is a chunk that was skipped due to failing the erased check */
+-
++                                      
+                               } else if (c == 0) {
+                                       /* We're looking at the first chunk in the block so the block is unused */
+                                       state = YAFFS_BLOCK_STATE_EMPTY;
+@@ -6140,7 +6208,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                           state == YAFFS_BLOCK_STATE_ALLOCATING) {
+                                               if(dev->sequenceNumber == bi->sequenceNumber) {
+                                                       /* this is the block being allocated from */
+-
++                                              
+                                                       T(YAFFS_TRACE_SCAN,
+                                                         (TSTR
+                                                          (" Allocating from %d %d"
+@@ -6149,34 +6217,41 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
+                                                       dev->allocationBlock = blk;
+                                                       dev->allocationPage = c;
+-                                                      dev->allocationBlockFinder = blk;
++                                                      dev->allocationBlockFinder = blk;       
+                                               }
+                                               else {
+                                                       /* This is a partially written block that is not
+                                                        * the current allocation block. This block must have
+                                                        * had a write failure, so set up for retirement.
+                                                        */
+-
+-                                                       bi->needsRetiring = 1;
++                                                
++                                                       /* bi->needsRetiring = 1; ??? TODO */
+                                                        bi->gcPrioritise = 1;
+-
++                                                                                                       
+                                                        T(YAFFS_TRACE_ALWAYS,
+-                                                       (TSTR("Partially written block %d being set for retirement" TENDSTR),
++                                                       (TSTR("Partially written block %d detected" TENDSTR),
+                                                        blk));
+                                               }
+                                       }
+-
++                                       
+                               }
+                               dev->nFreeChunks++;
++                              
++                      } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){
++                              T(YAFFS_TRACE_SCAN,
++                                (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR),
++                                blk, c));
+-                      } else if (tags.chunkId > 0) {
++                                dev->nFreeChunks++;
++
++                      }else if (tags.chunkId > 0) {
+                               /* chunkId > 0 so it is a data chunk... */
+                               unsigned int endpos;
+                               __u32 chunkBase =
+                                   (tags.chunkId - 1) * dev->nDataBytesPerChunk;
+-
++                                                              
+                               foundChunksInBlock = 1;
+@@ -6191,7 +6266,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                       /* Out of memory */
+                                       alloc_failed = 1;
+                               }
+-
++                              
+                               if (in &&
+                                   in->variantType == YAFFS_OBJECT_TYPE_FILE
+                                   && chunkBase <
+@@ -6202,14 +6277,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                               alloc_failed = 1;
+                                       }
+-                                      /* File size is calculated by looking at the data chunks if we have not
++                                      /* File size is calculated by looking at the data chunks if we have not 
+                                        * seen an object header yet. Stop this practice once we find an object header.
+                                        */
+                                       endpos =
+                                           (tags.chunkId -
+                                            1) * dev->nDataBytesPerChunk +
+                                           tags.byteCount;
+-
++                                          
+                                       if (!in->valid &&       /* have not got an object header yet */
+                                           in->variant.fileVariant.
+                                           scannedFileSize < endpos) {
+@@ -6255,7 +6330,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                   ) {
+                                       /* If we don't have  valid info then we need to read the chunk
+-                                       * TODO In future we can probably defer reading the chunk and
++                                       * TODO In future we can probably defer reading the chunk and 
+                                        * living with invalid data until needed.
+                                        */
+@@ -6265,6 +6340,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                                                       NULL);
+                                       oh = (yaffs_ObjectHeader *) chunkData;
++                                      
++                                      if(dev->inbandTags){
++                                              /* Fix up the header if they got corrupted by inband tags */
++                                              oh->shadowsObject = oh->inbandShadowsObject;
++                                              oh->isShrink = oh->inbandIsShrink;
++                                      }
+                                       if (!in)
+                                               in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
+@@ -6275,20 +6356,19 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                       /* TODO Hoosterman we have a problem! */
+                                       T(YAFFS_TRACE_ERROR,
+                                         (TSTR
+-                                         ("yaffs tragedy: Could not make object for object  %d  "
+-                                          "at chunk %d during scan"
++                                         ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"
+                                           TENDSTR), tags.objectId, chunk));
+                               }
+                               if (in->valid) {
+                                       /* We have already filled this one.
+-                                       * We have a duplicate that will be discarded, but
++                                       * We have a duplicate that will be discarded, but 
+                                        * we first have to suck out resize info if it is a file.
+                                        */
+-                                      if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
+-                                           ((oh &&
++                                      if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && 
++                                           ((oh && 
+                                              oh-> type == YAFFS_OBJECT_TYPE_FILE)||
+                                             (tags.extraHeaderInfoAvailable  &&
+                                              tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
+@@ -6300,7 +6380,9 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                                   (oh) ? oh->
+                                                   parentObjectId : tags.
+                                                   extraParentObjectId;
+-                                              unsigned isShrink =
++                                              
++                                              
++                                              isShrink =
+                                                   (oh) ? oh->isShrink : tags.
+                                                   extraIsShrinkHeader;
+@@ -6339,7 +6421,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                    YAFFS_OBJECTID_LOSTNFOUND)) {
+                                       /* We only load some info, don't fiddle with directory structure */
+                                       in->valid = 1;
+-
++                                      
+                                       if(oh) {
+                                               in->variantType = oh->type;
+@@ -6358,20 +6440,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                               in->yst_mtime = oh->yst_mtime;
+                                               in->yst_ctime = oh->yst_ctime;
+                                               in->yst_rdev = oh->yst_rdev;
+-
++              
+ #endif
+                                       } else {
+                                               in->variantType = tags.extraObjectType;
+                                               in->lazyLoaded = 1;
+                                       }
+-                                      in->chunkId = chunk;
++                                      in->hdrChunk = chunk;
+                               } else if (!in->valid) {
+                                       /* we need to load this info */
+                                       in->valid = 1;
+-                                      in->chunkId = chunk;
++                                      in->hdrChunk = chunk;
+                                       if(oh) {
+                                               in->variantType = oh->type;
+@@ -6393,12 +6475,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                               in->yst_rdev = oh->yst_rdev;
+ #endif
+-                                              if (oh->shadowsObject > 0)
++                                              if (oh->shadowsObject > 0) 
+                                                       yaffs_HandleShadowedObject(dev,
+                                                                          oh->
+                                                                          shadowsObject,
+                                                                          1);
+-
++                                      
+                                               yaffs_SetObjectName(in, oh->name);
+                                               parent =
+@@ -6431,13 +6513,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                       if (parent->variantType ==
+                                           YAFFS_OBJECT_TYPE_UNKNOWN) {
+-                                              /* Set up as a directory */
+-                                              parent->variantType =
+-                                                  YAFFS_OBJECT_TYPE_DIRECTORY;
+-                                              INIT_LIST_HEAD(&parent->variant.
+-                                                             directoryVariant.
+-                                                             children);
+-                                      } else if (parent->variantType !=
++                                                /* Set up as a directory */
++                                                parent->variantType =
++                                                    YAFFS_OBJECT_TYPE_DIRECTORY;
++                                                YINIT_LIST_HEAD(&parent->variant.
++                                                               directoryVariant.
++                                                               children);
++                                        } else if (parent->variantType !=
+                                                  YAFFS_OBJECT_TYPE_DIRECTORY)
+                                       {
+                                               /* Hoosterman, another problem....
+@@ -6446,8 +6528,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                               T(YAFFS_TRACE_ERROR,
+                                                 (TSTR
+-                                                 ("yaffs tragedy: attempting to use non-directory as"
+-                                                  " a directory in scan. Put in lost+found."
++                                                 ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
+                                                   TENDSTR)));
+                                               parent = dev->lostNFoundDir;
+                                       }
+@@ -6466,11 +6547,11 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                        * Since we might scan a hardlink before its equivalent object is scanned
+                                        * we put them all in a list.
+                                        * After scanning is complete, we should have all the objects, so we run
+-                                       * through this list and fix up all the chains.
++                                       * through this list and fix up all the chains.              
+                                        */
+                                       switch (in->variantType) {
+-                                      case YAFFS_OBJECT_TYPE_UNKNOWN:
++                                      case YAFFS_OBJECT_TYPE_UNKNOWN: 
+                                               /* Todo got a problem */
+                                               break;
+                                       case YAFFS_OBJECT_TYPE_FILE:
+@@ -6479,7 +6560,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                                   scannedFileSize < fileSize) {
+                                                       /* This covers the case where the file size is greater
+                                                        * than where the data is
+-                                                       * This will happen if the file is resized to be larger
++                                                       * This will happen if the file is resized to be larger 
+                                                        * than its current data extents.
+                                                        */
+                                                       in->variant.fileVariant.fileSize = fileSize;
+@@ -6495,13 +6576,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                               break;
+                                       case YAFFS_OBJECT_TYPE_HARDLINK:
+                                               if(!itsUnlinked) {
+-                                                in->variant.hardLinkVariant.equivalentObjectId =
+-                                                  equivalentObjectId;
+-                                                in->hardLinks.next =
+-                                                  (struct list_head *) hardList;
+-                                                hardList = in;
+-                                              }
+-                                              break;
++                                                  in->variant.hardLinkVariant.equivalentObjectId =
++                                                    equivalentObjectId;
++                                                  in->hardLinks.next =
++                                                    (struct ylist_head *) hardList;
++                                                  hardList = in;
++                                                }
++                                                break;
+                                       case YAFFS_OBJECT_TYPE_DIRECTORY:
+                                               /* Do nothing */
+                                               break;
+@@ -6520,7 +6601,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
+                                       }
+                               }
+-
++                              
+                       }
+               } /* End of scanning for each chunk */
+@@ -6541,72 +6622,128 @@ static int yaffs_ScanBackwards(yaffs_Dev
+       }
+-      if (altBlockIndex)
++      if (altBlockIndex) 
+               YFREE_ALT(blockIndex);
+       else
+               YFREE(blockIndex);
+-
++      
+       /* Ok, we've done all the scanning.
+        * Fix up the hard link chains.
+-       * We should now have scanned all the objects, now it's time to add these
++       * We should now have scanned all the objects, now it's time to add these 
+        * hardlinks.
+        */
+       yaffs_HardlinkFixup(dev,hardList);
++      
++      yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
++      
++      if(alloc_failed){
++              return YAFFS_FAIL;
++      }
+-      /*
+-      *  Sort out state of unlinked and deleted objects.
+-      */
+-      {
+-              struct list_head *i;
+-              struct list_head *n;
++      T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
+-              yaffs_Object *l;
++      return YAFFS_OK;
++}
+-              /* Soft delete all the unlinked files */
+-              list_for_each_safe(i, n,
+-                                 &dev->unlinkedDir->variant.directoryVariant.
+-                                 children) {
+-                      if (i) {
+-                              l = list_entry(i, yaffs_Object, siblings);
+-                              yaffs_DestroyObject(l);
+-                      }
+-              }
++/*------------------------------  Directory Functions ----------------------------- */
+-              /* Soft delete all the deletedDir files */
+-              list_for_each_safe(i, n,
+-                                 &dev->deletedDir->variant.directoryVariant.
+-                                 children) {
+-                      if (i) {
+-                              l = list_entry(i, yaffs_Object, siblings);
+-                              yaffs_DestroyObject(l);
++static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj)
++{
++        struct ylist_head *lh;
++        yaffs_Object *listObj;
++        
++        int count = 0;
+-                      }
+-              }
++      if(!obj){
++              T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR)));
++              YBUG();
+       }
+-      yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
++        if(yaffs_SkipVerification(obj->myDev))
++                return;
+-      if(alloc_failed){
+-              return YAFFS_FAIL;
++      if(!obj->parent){
++              T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR)));
++              YBUG();
++      }
++              
++      if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
++              T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR)));
++              YBUG();
++      }
++      
++        /* Iterate through the objects in each hash entry */
++         
++        ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) {
++              if (lh) {
++                        listObj = ylist_entry(lh, yaffs_Object, siblings);
++                      yaffs_VerifyObject(listObj);
++                      if(obj == listObj)
++                              count ++;
++                }
++       }
++       
++       if(count != 1){
++              T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR),count));
++              YBUG();
+       }
+-      T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
++}
+-      return YAFFS_OK;
++static void yaffs_VerifyDirectory(yaffs_Object *directory)
++{
++
++        struct ylist_head *lh;
++        yaffs_Object *listObj;
++        
++      if(!directory)
++              YBUG();
++
++        if(yaffs_SkipFullVerification(directory->myDev))
++                return;
++
++              
++      if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
++              T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR),directory->variantType));
++              YBUG();
++      }
++      
++        /* Iterate through the objects in each hash entry */
++         
++        ylist_for_each(lh, &directory->variant.directoryVariant.children) {
++              if (lh) {
++                        listObj = ylist_entry(lh, yaffs_Object, siblings);
++                      if(listObj->parent != directory){
++                              T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR),listObj->parent));
++                              YBUG();
++                      }
++                      yaffs_VerifyObjectInDirectory(listObj);
++                }
++       }
++       
+ }
+-/*------------------------------  Directory Functions ----------------------------- */
+ static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
+ {
+       yaffs_Device *dev = obj->myDev;
++      yaffs_Object *parent;
++      
++        yaffs_VerifyObjectInDirectory(obj);
++      parent = obj->parent;
++      
++      yaffs_VerifyDirectory(parent);
++
++        if(dev && dev->removeObjectCallback)
++                dev->removeObjectCallback(obj);
++
++           
++        ylist_del_init(&obj->siblings);
++        obj->parent = NULL;
+-      if(dev && dev->removeObjectCallback)
+-              dev->removeObjectCallback(obj);
++      yaffs_VerifyDirectory(parent);
+-      list_del_init(&obj->siblings);
+-      obj->parent = NULL;
+ }
+@@ -6629,35 +6766,46 @@ static void yaffs_AddObjectToDirectory(y
+               YBUG();
+       }
+-      if (obj->siblings.prev == NULL) {
+-              /* Not initialised */
+-              INIT_LIST_HEAD(&obj->siblings);
+-
+-      } else if (!list_empty(&obj->siblings)) {
+-              /* If it is holed up somewhere else, un hook it */
+-              yaffs_RemoveObjectFromDirectory(obj);
+-      }
+-      /* Now add it */
+-      list_add(&obj->siblings, &directory->variant.directoryVariant.children);
+-      obj->parent = directory;
++        if (obj->siblings.prev == NULL) {
++                /* Not initialised */
++                YBUG();
++
++        } else if (ylist_empty(&obj->siblings)) {
++              YBUG();
++        } 
++
+-      if (directory == obj->myDev->unlinkedDir
++      yaffs_VerifyDirectory(directory);
++
++      yaffs_RemoveObjectFromDirectory(obj);
++        
++        
++        /* Now add it */
++        ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
++        obj->parent = directory;
++
++        if (directory == obj->myDev->unlinkedDir
+           || directory == obj->myDev->deletedDir) {
+               obj->unlinked = 1;
+               obj->myDev->nUnlinkedFiles++;
+               obj->renameAllowed = 0;
+       }
++
++      yaffs_VerifyDirectory(directory);
++        yaffs_VerifyObjectInDirectory(obj);
++
++
+ }
+ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
+                                    const YCHAR * name)
+ {
+-      int sum;
++        int sum;
+-      struct list_head *i;
+-      YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
++        struct ylist_head *i;
++        YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
+-      yaffs_Object *l;
++        yaffs_Object *l;
+       if (!name) {
+               return NULL;
+@@ -6677,22 +6825,24 @@ yaffs_Object *yaffs_FindObjectByName(yaf
+               YBUG();
+       }
+-      sum = yaffs_CalcNameSum(name);
++        sum = yaffs_CalcNameSum(name);
+-      list_for_each(i, &directory->variant.directoryVariant.children) {
+-              if (i) {
+-                      l = list_entry(i, yaffs_Object, siblings);
+-
+-                      yaffs_CheckObjectDetailsLoaded(l);
++        ylist_for_each(i, &directory->variant.directoryVariant.children) {
++                if (i) {
++                        l = ylist_entry(i, yaffs_Object, siblings);
++                        
++                        if(l->parent != directory)
++                              YBUG();
++                        
++                        yaffs_CheckObjectDetailsLoaded(l);
+                       /* Special case for lost-n-found */
+                       if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
+                               if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
+                                       return l;
+                               }
+-                      } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
+-                      {
+-                              /* LostnFound cunk called Objxxx
++                      } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0){
++                              /* LostnFound chunk called Objxxx
+                                * Do a real check
+                                */
+                               yaffs_GetObjectName(l, buffer,
+@@ -6711,12 +6861,12 @@ yaffs_Object *yaffs_FindObjectByName(yaf
+ #if 0
+ int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
+-                                 int (*fn) (yaffs_Object *))
++                                   int (*fn) (yaffs_Object *))
+ {
+-      struct list_head *i;
+-      yaffs_Object *l;
++        struct ylist_head *i;
++        yaffs_Object *l;
+-      if (!theDir) {
++        if (!theDir) {
+               T(YAFFS_TRACE_ALWAYS,
+                 (TSTR
+                  ("tragedy: yaffs_FindObjectByName: null pointer directory"
+@@ -6727,15 +6877,15 @@ int yaffs_ApplyToDirectoryChildren(yaffs
+               T(YAFFS_TRACE_ALWAYS,
+                 (TSTR
+                  ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
+-              YBUG();
+-      }
++                YBUG();
++        }
+-      list_for_each(i, &theDir->variant.directoryVariant.children) {
+-              if (i) {
+-                      l = list_entry(i, yaffs_Object, siblings);
+-                      if (l && !fn(l)) {
+-                              return YAFFS_FAIL;
+-                      }
++        ylist_for_each(i, &theDir->variant.directoryVariant.children) {
++                if (i) {
++                        l = ylist_entry(i, yaffs_Object, siblings);
++                        if (l && !fn(l)) {
++                                return YAFFS_FAIL;
++                        }
+               }
+       }
+@@ -6762,16 +6912,25 @@ yaffs_Object *yaffs_GetEquivalentObject(
+ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
+ {
+       memset(name, 0, buffSize * sizeof(YCHAR));
+-
++      
+       yaffs_CheckObjectDetailsLoaded(obj);
+       if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
+               yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
+-      } else if (obj->chunkId <= 0) {
++      } else if (obj->hdrChunk <= 0) {
+               YCHAR locName[20];
++              YCHAR numString[20];
++              YCHAR *x = &numString[19];
++              unsigned v = obj->objectId;
++              numString[19] = 0;
++              while(v>0){
++                      x--;
++                      *x = '0' + (v % 10);
++                      v /= 10;
++              }
+               /* make up a name */
+-              yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
+-                            obj->objectId);
++              yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX);
++              yaffs_strcat(locName,x);
+               yaffs_strncpy(name, locName, buffSize - 1);
+       }
+@@ -6788,9 +6947,9 @@ int yaffs_GetObjectName(yaffs_Object * o
+               memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
+-              if (obj->chunkId >= 0) {
++              if (obj->hdrChunk > 0) {
+                       result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
+-                                                      obj->chunkId, buffer,
++                                                      obj->hdrChunk, buffer,
+                                                       NULL);
+               }
+               yaffs_strncpy(name, oh->name, buffSize - 1);
+@@ -6820,16 +6979,16 @@ int yaffs_GetObjectFileLength(yaffs_Obje
+ int yaffs_GetObjectLinkCount(yaffs_Object * obj)
+ {
+-      int count = 0;
+-      struct list_head *i;
++        int count = 0;
++        struct ylist_head *i;
+-      if (!obj->unlinked) {
+-              count++;        /* the object itself */
+-      }
+-      list_for_each(i, &obj->hardLinks) {
+-              count++;        /* add the hard links; */
+-      }
+-      return count;
++        if (!obj->unlinked) {
++                count++;        /* the object itself */
++        }
++        ylist_for_each(i, &obj->hardLinks) {
++                count++;        /* add the hard links; */
++        }
++        return count;
+ }
+@@ -6951,7 +7110,7 @@ int yaffs_DumpObject(yaffs_Object * obj)
+          ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
+           " chunk %d type %d size %d\n"
+           TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
+-         obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
++         obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk,
+          yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
+       return YAFFS_OK;
+@@ -6994,13 +7153,13 @@ static int yaffs_CheckDevFunctions(const
+ static int yaffs_CreateInitialDirectories(yaffs_Device *dev)
+ {
+       /* Initialise the unlinked, deleted, root and lost and found directories */
+-
++      
+       dev->lostNFoundDir = dev->rootDir =  NULL;
+       dev->unlinkedDir = dev->deletedDir = NULL;
+       dev->unlinkedDir =
+           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
+-
++      
+       dev->deletedDir =
+           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
+@@ -7010,12 +7169,12 @@ static int yaffs_CreateInitialDirectorie
+       dev->lostNFoundDir =
+           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
+                                     YAFFS_LOSTNFOUND_MODE | S_IFDIR);
+-
++      
+       if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){
+               yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
+               return YAFFS_OK;
+       }
+-
++      
+       return YAFFS_FAIL;
+ }
+@@ -7039,6 +7198,8 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       dev->blockOffset = 0;
+       dev->chunkOffset = 0;
+       dev->nFreeChunks = 0;
++      
++      dev->gcBlock = -1;
+       if (dev->startBlock == 0) {
+               dev->internalStartBlock = dev->startBlock + 1;
+@@ -7049,18 +7210,19 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       /* Check geometry parameters. */
+-      if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
+-          (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
+-           dev->nChunksPerBlock < 2 ||
+-           dev->nReservedBlocks < 2 ||
+-           dev->internalStartBlock <= 0 ||
+-           dev->internalEndBlock <= 0 ||
++      if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || 
++          (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || 
++          (dev->inbandTags && !dev->isYaffs2 ) ||
++           dev->nChunksPerBlock < 2 || 
++           dev->nReservedBlocks < 2 || 
++           dev->internalStartBlock <= 0 || 
++           dev->internalEndBlock <= 0 || 
+            dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)      // otherwise it is too small
+           ) {
+               T(YAFFS_TRACE_ALWAYS,
+                 (TSTR
+-                 ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
+-                  TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
++                 ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
++                  TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
+               return YAFFS_FAIL;
+       }
+@@ -7069,6 +7231,12 @@ int yaffs_GutsInitialise(yaffs_Device * 
+                 (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
+               return YAFFS_FAIL;
+       }
++      
++      /* Sort out space for inband tags, if required */
++      if(dev->inbandTags)
++              dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
++      else 
++              dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
+       /* Got the right mix of functions? */
+       if (!yaffs_CheckDevFunctions(dev)) {
+@@ -7097,41 +7265,28 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       dev->isMounted = 1;
+-
+-
+       /* OK now calculate a few things for the device */
+-
++      
+       /*
+-       *  Calculate all the chunk size manipulation numbers:
++       *  Calculate all the chunk size manipulation numbers:   
+        */
+-       /* Start off assuming it is a power of 2 */
+-       dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
+-       dev->chunkMask = (1<<dev->chunkShift) - 1;
+-
+-       if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
+-              /* Yes it is a power of 2, disable crumbs */
+-              dev->crumbMask = 0;
+-              dev->crumbShift = 0;
+-              dev->crumbsPerChunk = 0;
+-       } else {
+-              /* Not a power of 2, use crumbs instead */
+-              dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
+-              dev->crumbMask = (1<<dev->crumbShift)-1;
+-              dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
+-              dev->chunkShift = 0;
+-              dev->chunkMask = 0;
+-      }
+-
+-
++      x = dev->nDataBytesPerChunk;
++      /* We always use dev->chunkShift and dev->chunkDiv */
++      dev->chunkShift = Shifts(x);
++      x >>= dev->chunkShift;
++      dev->chunkDiv = x;
++      /* We only use chunk mask if chunkDiv is 1 */
++      dev->chunkMask = (1<<dev->chunkShift) - 1;
++              
+       /*
+        * Calculate chunkGroupBits.
+        * We need to find the next power of 2 > than internalEndBlock
+        */
+       x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
+-
++      
+       bits = ShiftsGE(x);
+-
++      
+       /* Set up tnode width if wide tnodes are enabled. */
+       if(!dev->wideTnodesDisabled){
+               /* bits must be even so that we end up with 32-bit words */
+@@ -7144,20 +7299,20 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       }
+       else
+               dev->tnodeWidth = 16;
+-
++ 
+       dev->tnodeMask = (1<<dev->tnodeWidth)-1;
+-
++              
+       /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
+        * so if the bitwidth of the
+        * chunk range we're using is greater than 16 we need
+        * to figure out chunk shift and chunkGroupSize
+        */
+-
++               
+       if (bits <= dev->tnodeWidth)
+               dev->chunkGroupBits = 0;
+       else
+               dev->chunkGroupBits = bits - dev->tnodeWidth;
+-
++              
+       dev->chunkGroupSize = 1 << dev->chunkGroupBits;
+@@ -7195,40 +7350,42 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       /* Initialise temporary buffers and caches. */
+       if(!yaffs_InitialiseTempBuffers(dev))
+               init_failed = 1;
+-
++      
+       dev->srCache = NULL;
+       dev->gcCleanupList = NULL;
+-
+-
++      
++      
+       if (!init_failed &&
+           dev->nShortOpCaches > 0) {
+               int i;
+-              __u8 *buf;
++              void *buf;
+               int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
+               if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
+                       dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
+               }
+-              buf = dev->srCache =  YMALLOC(srCacheBytes);
+-
++              dev->srCache =  YMALLOC(srCacheBytes);
++              
++              buf = (__u8 *) dev->srCache;
++                  
+               if(dev->srCache)
+                       memset(dev->srCache,0,srCacheBytes);
+-
++                 
+               for (i = 0; i < dev->nShortOpCaches && buf; i++) {
+                       dev->srCache[i].object = NULL;
+                       dev->srCache[i].lastUse = 0;
+                       dev->srCache[i].dirty = 0;
+-                      dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
++                      dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
+               }
+               if(!buf)
+                       init_failed = 1;
+-
++                      
+               dev->srLastUse = 0;
+       }
+       dev->cacheHits = 0;
+-
++      
+       if(!init_failed){
+               dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
+               if(!dev->gcCleanupList)
+@@ -7240,7 +7397,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       }
+       if(!init_failed && !yaffs_InitialiseBlocks(dev))
+               init_failed = 1;
+-
++              
+       yaffs_InitialiseTnodes(dev);
+       yaffs_InitialiseObjects(dev);
+@@ -7252,18 +7409,19 @@ int yaffs_GutsInitialise(yaffs_Device * 
+               /* Now scan the flash. */
+               if (dev->isYaffs2) {
+                       if(yaffs_CheckpointRestore(dev)) {
++                              yaffs_CheckObjectDetailsLoaded(dev->rootDir);
+                               T(YAFFS_TRACE_ALWAYS,
+                                 (TSTR("yaffs: restored from checkpoint" TENDSTR)));
+                       } else {
+-                              /* Clean up the mess caused by an aborted checkpoint load
+-                               * and scan backwards.
++                              /* Clean up the mess caused by an aborted checkpoint load 
++                               * and scan backwards. 
+                                */
+                               yaffs_DeinitialiseBlocks(dev);
+                               yaffs_DeinitialiseTnodes(dev);
+                               yaffs_DeinitialiseObjects(dev);
+-
+-
++                              
++                      
+                               dev->nErasedBlocks = 0;
+                               dev->nFreeChunks = 0;
+                               dev->allocationBlock = -1;
+@@ -7275,7 +7433,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
+                               if(!init_failed && !yaffs_InitialiseBlocks(dev))
+                                       init_failed = 1;
+-
++                                      
+                               yaffs_InitialiseTnodes(dev);
+                               yaffs_InitialiseObjects(dev);
+@@ -7288,8 +7446,10 @@ int yaffs_GutsInitialise(yaffs_Device * 
+               }else
+                       if(!yaffs_Scan(dev))
+                               init_failed = 1;
+-      }
++              yaffs_StripDeletedObjects(dev);
++      }
++              
+       if(init_failed){
+               /* Clean up the mess */
+               T(YAFFS_TRACE_TRACING,
+@@ -7310,7 +7470,7 @@ int yaffs_GutsInitialise(yaffs_Device * 
+       yaffs_VerifyFreeChunks(dev);
+       yaffs_VerifyBlocks(dev);
+-
++      
+       T(YAFFS_TRACE_TRACING,
+         (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
+@@ -7345,7 +7505,11 @@ void yaffs_Deinitialise(yaffs_Device * d
+                       YFREE(dev->tempBuffer[i].buffer);
+               }
++
+               dev->isMounted = 0;
++              
++              if(dev->deinitialiseNAND)
++                      dev->deinitialiseNAND(dev);
+       }
+ }
+@@ -7394,7 +7558,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
+ #endif
+       nFree += dev->nDeletedFiles;
+-
++      
+       /* Now count the number of dirty chunks in the cache and subtract those */
+       {
+@@ -7408,12 +7572,12 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
+       nFree -= nDirtyCacheChunks;
+       nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
+-
++      
+       /* Now we figure out how much to reserve for the checkpoint and report that... */
+-      blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
++      blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
+       if(blocksForCheckpoint < 0)
+               blocksForCheckpoint = 0;
+-
++              
+       nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
+       if (nFree < 0)
+@@ -7429,10 +7593,10 @@ static void yaffs_VerifyFreeChunks(yaffs
+ {
+       int counted;
+       int difference;
+-
++      
+       if(yaffs_SkipVerification(dev))
+               return;
+-
++      
+       counted = yaffs_CountFreeChunks(dev);
+       difference = dev->nFreeChunks - counted;
+@@ -7448,22 +7612,25 @@ static void yaffs_VerifyFreeChunks(yaffs
+ /*---------------------------------------- YAFFS test code ----------------------*/
+ #define yaffs_CheckStruct(structure,syze, name) \
++      do { \
+            if(sizeof(structure) != syze) \
+              { \
+                T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
+                name,syze,sizeof(structure))); \
+                return YAFFS_FAIL; \
+-              }
++              } \
++      } while(0)
+ static int yaffs_CheckStructures(void)
+ {
+-/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
+-/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
+-/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
++/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */
++/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */
++/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */
+ #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
+-      yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
++        yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
++#endif
++#ifndef CONFIG_YAFFS_WINCE
++              yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
+ #endif
+-          yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
+-
+           return YAFFS_OK;
+ }
+--- a/fs/yaffs2/yaffs_mtdif1.c
++++ b/fs/yaffs2/yaffs_mtdif1.c
+@@ -34,9 +34,9 @@
+ #include "linux/mtd/mtd.h"
+ /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+-const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $";
++const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.8 2008-07-23 03:35:12 charles Exp $";
+ #ifndef CONFIG_YAFFS_9BYTE_TAGS
+ # define YTAG1_SIZE 8
+@@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
+       ops.datbuf = data;
+       ops.oobbuf = (__u8 *)&pt1;
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
++#if (MTD_VERSION_CODE < MTD_VERSION(2,6,20))
+       /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+        * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+        */
+@@ -288,7 +288,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaf
+       int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
+       int retval;
+-      yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
++      yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
+       retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
+       return (retval) ? YAFFS_FAIL : YAFFS_OK;
+@@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(stru
+  * Always returns YAFFS_OK.
+  */
+ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+-      yaffs_BlockState * pState, int *pSequenceNumber)
++      yaffs_BlockState * pState, __u32 *pSequenceNumber)
+ {
+       struct mtd_info * mtd = dev->genericDevice;
+       int chunkNo = blockNo * dev->nChunksPerBlock;
++      loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
+       yaffs_ExtendedTags etags;
+       int state = YAFFS_BLOCK_STATE_DEAD;
+       int seqnum = 0;
+@@ -340,11 +341,16 @@ int nandmtd1_QueryNANDBlock(struct yaffs
+       }
+       retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
++      etags.blockBad = (mtd->block_isbad)(mtd, addr);
+       if (etags.blockBad) {
+               yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
+-                      "block %d is marked bad", blockNo);
++                      "block %d is marked bad\n", blockNo);
+               state = YAFFS_BLOCK_STATE_DEAD;
+       }
++      else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
++              /* bad tags, need to look more closely */
++              state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
++      }
+       else if (etags.chunkUsed) {
+               state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+               seqnum = etags.sequenceNumber;
+@@ -360,4 +366,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs
+       return YAFFS_OK;
+ }
+-#endif /*KERNEL_VERSION*/
++#endif /*MTD_VERSION*/
+--- a/fs/yaffs2/yaffs_mtdif2.c
++++ b/fs/yaffs2/yaffs_mtdif2.c
+@@ -14,7 +14,7 @@
+ /* mtd interface for YAFFS2 */
+ const char *yaffs_mtdif2_c_version =
+-    "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $";
++    "$Id: yaffs_mtdif2.c,v 1.22 2008-11-02 22:47:13 charles Exp $";
+ #include "yportenv.h"
+@@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version =
+ #include "yaffs_packedtags2.h"
++/* NB For use with inband tags....
++ * We assume that the data buffer is of size totalBytersPerChunk so that we can also
++ * use it to load the tags.
++ */
+ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
+                                     const __u8 * data,
+                                     const yaffs_ExtendedTags * tags)
+ {
+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+       struct mtd_oob_ops ops;
+ #else
+       size_t dummy;
+ #endif
+       int retval = 0;
+-      loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
++      loff_t addr;
+       yaffs_PackedTags2 pt;
+@@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
+         (TSTR
+          ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
+           TENDSTR), chunkInNAND, data, tags));
++          
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-      if (tags)
+-              yaffs_PackTags2(&pt, tags);
++      addr  = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
++      
++      /* For yaffs2 writing there must be both data and tags.
++       * If we're using inband tags, then the tags are stuffed into
++       * the end of the data buffer.
++       */
++      if(!data || !tags)
++              BUG();  
++      else if(dev->inbandTags){
++              yaffs_PackedTags2TagsPart *pt2tp;
++              pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
++              yaffs_PackTags2TagsPart(pt2tp,tags);
++      }
+       else
+-              BUG(); /* both tags and data should always be present */
+-
+-      if (data) {
+-              ops.mode = MTD_OOB_AUTO;
+-              ops.ooblen = sizeof(pt);
+-              ops.len = dev->nDataBytesPerChunk;
+-              ops.ooboffs = 0;
+-              ops.datbuf = (__u8 *)data;
+-              ops.oobbuf = (void *)&pt;
+-              retval = mtd->write_oob(mtd, addr, &ops);
+-      } else
+-              BUG(); /* both tags and data should always be present */
+-#else
+-      if (tags) {
+               yaffs_PackTags2(&pt, tags);
+-      }
++      
++#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++      ops.mode = MTD_OOB_AUTO;
++      ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
++      ops.len = dev->totalBytesPerChunk;
++      ops.ooboffs = 0;
++      ops.datbuf = (__u8 *)data;
++      ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
++      retval = mtd->write_oob(mtd, addr, &ops);
+-      if (data && tags) {
+-              if (dev->useNANDECC)
+-                      retval =
+-                          mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+-                                         &dummy, data, (__u8 *) & pt, NULL);
+-              else
+-                      retval =
+-                          mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
+-                                         &dummy, data, (__u8 *) & pt, NULL);
++#else
++      if (!dev->inbandTags) {
++              retval =
++                  mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
++                                 &dummy, data, (__u8 *) & pt, NULL);
+       } else {
+-              if (data)
+-                      retval =
+-                          mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+-                                     data);
+-              if (tags)
+-                      retval =
+-                          mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
+-                                         (__u8 *) & pt);
+-
++              retval =
++                  mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
++                             data);
+       }
+ #endif
+@@ -101,13 +100,14 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
+                                      __u8 * data, yaffs_ExtendedTags * tags)
+ {
+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+       struct mtd_oob_ops ops;
+ #endif
+       size_t dummy;
+       int retval = 0;
++      int localData = 0;
+-      loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
++      loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
+       yaffs_PackedTags2 pt;
+@@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
+         (TSTR
+          ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
+           TENDSTR), chunkInNAND, data, tags));
++          
++      if(dev->inbandTags){
++              
++              if(!data) {
++                      localData = 1;
++                      data = yaffs_GetTempBuffer(dev,__LINE__);
++              }
++              
++
++      }
++
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-      if (data && !tags)
+-              retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
++      if (dev->inbandTags || (data && !tags))
++              retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
+                               &dummy, data);
+       else if (tags) {
+               ops.mode = MTD_OOB_AUTO;
+@@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
+               retval = mtd->read_oob(mtd, addr, &ops);
+       }
+ #else
+-      if (data && tags) {
+-              if (dev->useNANDECC) {
+-                      retval =
+-                          mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+-                                        &dummy, data, dev->spareBuffer,
+-                                        NULL);
+-              } else {
+-                      retval =
+-                          mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
++      if (!dev->inbandTags && data && tags) {
++
++              retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
+                                         &dummy, data, dev->spareBuffer,
+                                         NULL);
+-              }
+       } else {
+               if (data)
+                       retval =
+                           mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
+                                     data);
+-              if (tags)
++              if (!dev->inbandTags && tags)
+                       retval =
+                           mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
+                                         dev->spareBuffer);
+       }
+ #endif
+-      memcpy(&pt, dev->spareBuffer, sizeof(pt));
+-      if (tags)
+-              yaffs_UnpackTags2(tags, &pt);
++      if(dev->inbandTags){
++              if(tags){
++                      yaffs_PackedTags2TagsPart * pt2tp;
++                      pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];    
++                      yaffs_UnpackTags2TagsPart(tags,pt2tp);
++              }
++      }
++      else {
++              if (tags){
++                      memcpy(&pt, dev->spareBuffer, sizeof(pt));
++                      yaffs_UnpackTags2(tags, &pt);
++              }
++      }
++      if(localData)
++              yaffs_ReleaseTempBuffer(dev,data,__LINE__);
++      
+       if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
+-              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
+-
++              tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;             
+       if (retval == 0)
+               return YAFFS_OK;
+       else
+@@ -178,7 +194,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
+       retval =
+           mtd->block_markbad(mtd,
+                              blockNo * dev->nChunksPerBlock *
+-                             dev->nDataBytesPerChunk);
++                             dev->totalBytesPerChunk);
+       if (retval == 0)
+               return YAFFS_OK;
+@@ -188,7 +204,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
+ }
+ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+-                          yaffs_BlockState * state, int *sequenceNumber)
++                          yaffs_BlockState * state, __u32 *sequenceNumber)
+ {
+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+       int retval;
+@@ -198,7 +214,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs
+       retval =
+           mtd->block_isbad(mtd,
+                            blockNo * dev->nChunksPerBlock *
+-                           dev->nDataBytesPerChunk);
++                           dev->totalBytesPerChunk);
+       if (retval) {
+               T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
+--- a/fs/yaffs2/yaffs_guts.h
++++ b/fs/yaffs2/yaffs_guts.h
+@@ -1,5 +1,5 @@
+ /*
+- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
++ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
+  *
+  * Copyright (C) 2002-2007 Aleph One Ltd.
+  *   for Toby Churchill Ltd and Brightstar Engineering
+@@ -22,11 +22,11 @@
+ #define YAFFS_OK      1
+ #define YAFFS_FAIL  0
+-/* Give us a  Y=0x59,
+- * Give us an A=0x41,
+- * Give us an FF=0xFF
++/* Give us a  Y=0x59, 
++ * Give us an A=0x41, 
++ * Give us an FF=0xFF 
+  * Give us an S=0x53
+- * And what have we got...
++ * And what have we got... 
+  */
+ #define YAFFS_MAGIC                   0x5941FF53
+@@ -90,7 +90,7 @@
+ #define YAFFS_MAX_SHORT_OP_CACHES     20
+-#define YAFFS_N_TEMP_BUFFERS          4
++#define YAFFS_N_TEMP_BUFFERS          6
+ /* We limit the number attempts at sucessfully saving a chunk of data.
+  * Small-page devices have 32 pages per block; large-page devices have 64.
+@@ -102,7 +102,7 @@
+  * The range is limited slightly to help distinguish bad numbers from good.
+  * This also allows us to perhaps in the future use special numbers for
+  * special purposes.
+- * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
++ * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, 
+  * and is a larger number than the lifetime of a 2GB device.
+  */
+ #define YAFFS_LOWEST_SEQUENCE_NUMBER  0x00001000
+@@ -132,12 +132,12 @@ typedef struct {
+ #ifndef CONFIG_YAFFS_NO_YAFFS1
+ typedef struct {
+-      unsigned chunkId:20;
+-      unsigned serialNumber:2;
+-      unsigned byteCount:10;
+-      unsigned objectId:18;
+-      unsigned ecc:12;
+-      unsigned unusedStuff:2;
++        unsigned chunkId:20;
++        unsigned serialNumber:2;
++        unsigned byteCountLSB:10;
++        unsigned objectId:18;
++        unsigned ecc:12;
++        unsigned byteCountMSB:2;
+ } yaffs_Tags;
+@@ -178,7 +178,7 @@ typedef struct {
+       /* The following stuff only has meaning when we read */
+       yaffs_ECCResult eccResult;
+-      unsigned blockBad;
++      unsigned blockBad;      
+       /* YAFFS 1 stuff */
+       unsigned chunkDeleted;  /* The chunk is marked deleted */
+@@ -244,29 +244,29 @@ typedef enum {
+       /* This block is empty */
+       YAFFS_BLOCK_STATE_ALLOCATING,
+-      /* This block is partially allocated.
++      /* This block is partially allocated. 
+        * At least one page holds valid data.
+        * This is the one currently being used for page
+        * allocation. Should never be more than one of these
+        */
+-      YAFFS_BLOCK_STATE_FULL,
++      YAFFS_BLOCK_STATE_FULL, 
+       /* All the pages in this block have been allocated.
+        */
+       YAFFS_BLOCK_STATE_DIRTY,
+-      /* All pages have been allocated and deleted.
++      /* All pages have been allocated and deleted. 
+        * Erase me, reuse me.
+        */
+-      YAFFS_BLOCK_STATE_CHECKPOINT,
++      YAFFS_BLOCK_STATE_CHECKPOINT,   
+       /* This block is assigned to holding checkpoint data.
+        */
+-      YAFFS_BLOCK_STATE_COLLECTING,
++      YAFFS_BLOCK_STATE_COLLECTING,   
+       /* This block is being garbage collected */
+-      YAFFS_BLOCK_STATE_DEAD
++      YAFFS_BLOCK_STATE_DEAD  
+       /* This block has failed and is not in use */
+ } yaffs_BlockState;
+@@ -277,11 +277,11 @@ typedef struct {
+       int softDeletions:10;   /* number of soft deleted pages */
+       int pagesInUse:10;      /* number of pages in use */
+-      yaffs_BlockState blockState:4;  /* One of the above block states */
++      unsigned blockState:4;  /* One of the above block states. NB use unsigned because enum is sometimes an int */
+       __u32 needsRetiring:1;  /* Data has failed on this block, need to get valid data off */
+                               /* and retire the block. */
+       __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
+-      __u32 gcPrioritise: 1;  /* An ECC check or blank check has failed on this block.
++      __u32 gcPrioritise: 1;  /* An ECC check or blank check has failed on this block. 
+                                  It should be prioritised for GC */
+         __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
+@@ -300,11 +300,11 @@ typedef struct {
+       /* Apply to everything  */
+       int parentObjectId;
+-      __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
+-      YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
++        __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
++        YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
+-      /* Thes following apply to directories, files, symlinks - not hard links */
+-      __u32 yst_mode;         /* protection */
++        /* The following apply to directories, files, symlinks - not hard links */
++        __u32 yst_mode;         /* protection */
+ #ifdef CONFIG_YAFFS_WINCE
+       __u32 notForWinCE[5];
+@@ -331,11 +331,14 @@ typedef struct {
+       __u32 win_ctime[2];
+       __u32 win_atime[2];
+       __u32 win_mtime[2];
+-      __u32 roomToGrow[4];
+ #else
+-      __u32 roomToGrow[10];
++      __u32 roomToGrow[6];
++
+ #endif
++      __u32 inbandShadowsObject;
++      __u32 inbandIsShrink;
++      __u32 reservedSpace[2];
+       int shadowsObject;      /* This object header shadows the specified object if > 0 */
+       /* isShrink applies to object headers written when we shrink the file (ie resize) */
+@@ -381,7 +384,7 @@ typedef struct {
+ } yaffs_FileStructure;
+ typedef struct {
+-      struct list_head children;      /* list of child links */
++        struct ylist_head children;     /* list of child links */
+ } yaffs_DirectoryStructure;
+ typedef struct {
+@@ -408,7 +411,7 @@ struct yaffs_ObjectStruct {
+       __u8 renameAllowed:1;   /* Some objects are not allowed to be renamed. */
+       __u8 unlinkAllowed:1;
+       __u8 dirty:1;           /* the object needs to be written to flash */
+-      __u8 valid:1;           /* When the file system is being loaded up, this
++      __u8 valid:1;           /* When the file system is being loaded up, this 
+                                * object might be created before the data
+                                * is available (ie. file data records appear before the header).
+                                */
+@@ -417,33 +420,36 @@ struct yaffs_ObjectStruct {
+       __u8 deferedFree:1;     /* For Linux kernel. Object is removed from NAND, but is
+                                * still in the inode cache. Free of object is defered.
+                                * until the inode is released.
+-                               */
++                                 */
++        __u8 beingCreated:1;  /* This object is still being created so skip some checks. */
+-      __u8 serial;            /* serial number of chunk in NAND. Cached here */
+-      __u16 sum;              /* sum of the name to speed searching */
++        __u8 serial;            /* serial number of chunk in NAND. Cached here */
++/*        __u16 sum_prev; */
++        __u16 sum;              /* sum of the name to speed searching */
++/*        __u16 sum_trailer; */
+-      struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
++        struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
+-      struct list_head hashLink;      /* list of objects in this hash bucket */
++        struct ylist_head hashLink;     /* list of objects in this hash bucket */
+-      struct list_head hardLinks;     /* all the equivalent hard linked objects */
++        struct ylist_head hardLinks;    /* all the equivalent hard linked objects */
+-      /* directory structure stuff */
+-      /* also used for linking up the free list */
+-      struct yaffs_ObjectStruct *parent;
+-      struct list_head siblings;
++        /* directory structure stuff */
++        /* also used for linking up the free list */
++        struct yaffs_ObjectStruct *parent; 
++        struct ylist_head siblings;
+       /* Where's my object header in NAND? */
+-      int chunkId;
++      int hdrChunk;
+       int nDataChunks;        /* Number of data chunks attached to the file. */
+       __u32 objectId;         /* the object id value */
+-      __u32 yst_mode;
++        __u32 yst_mode;
+ #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+-      YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
++        YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
+ #endif
+ #ifndef __KERNEL__
+@@ -485,31 +491,30 @@ struct yaffs_ObjectList_struct {
+ typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
+ typedef struct {
+-      struct list_head list;
+-      int count;
++        struct ylist_head list;
++        int count;
+ } yaffs_ObjectBucket;
+-/* yaffs_CheckpointObject holds the definition of an object as dumped
++/* yaffs_CheckpointObject holds the definition of an object as dumped 
+  * by checkpointing.
+  */
+ typedef struct {
+         int structType;
+-      __u32 objectId;
++      __u32 objectId;         
+       __u32 parentId;
+-      int chunkId;
+-
++      int hdrChunk;
+       yaffs_ObjectType variantType:3;
+-      __u8 deleted:1;
+-      __u8 softDeleted:1;
+-      __u8 unlinked:1;
+-      __u8 fake:1;
++      __u8 deleted:1;         
++      __u8 softDeleted:1;     
++      __u8 unlinked:1;        
++      __u8 fake:1;            
+       __u8 renameAllowed:1;
+       __u8 unlinkAllowed:1;
+-      __u8 serial;
+-
+-      int nDataChunks;
++      __u8 serial;            
++      
++      int nDataChunks;        
+       __u32 fileSizeOrEquivalentObjectId;
+ }yaffs_CheckpointObject;
+@@ -528,25 +533,25 @@ typedef struct {
+ /*----------------- Device ---------------------------------*/
+ struct yaffs_DeviceStruct {
+-      struct list_head devList;
+-      const char *name;
++        struct ylist_head devList;
++        const char *name;
+-      /* Entry parameters set up way early. Yaffs sets up the rest.*/
+-      int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
+-      int nChunksPerBlock;    /* does not need to be a power of 2 */
+-      int nBytesPerSpare;     /* spare area size */
+-      int startBlock;         /* Start block we're allowed to use */
+-      int endBlock;           /* End block we're allowed to use */
+-      int nReservedBlocks;    /* We want this tuneable so that we can reduce */
++        /* Entry parameters set up way early. Yaffs sets up the rest.*/
++        int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
++        int nChunksPerBlock;    /* does not need to be a power of 2 */
++        int spareBytesPerChunk;/* spare area size */
++        int startBlock;         /* Start block we're allowed to use */
++        int endBlock;           /* End block we're allowed to use */
++        int nReservedBlocks;    /* We want this tuneable so that we can reduce */
+                               /* reserved blocks on NOR and RAM. */
+-
+-
++      
++      
+       /* Stuff used by the shared space checkpointing mechanism */
+       /* If this value is zero, then this mechanism is disabled */
++      
++//    int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
+-      int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
+-
+-
++      
+       int nShortOpCaches;     /* If <= 0, then short op caching is disabled, else
+@@ -561,7 +566,7 @@ struct yaffs_DeviceStruct {
+                                * On an mtd this holds the mtd pointer.
+                                */
+         void *superBlock;
+-
++        
+       /* NAND access functions (Must be set before calling YAFFS)*/
+       int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
+@@ -570,12 +575,13 @@ struct yaffs_DeviceStruct {
+       int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
+                                 int chunkInNAND, __u8 * data,
+                                 yaffs_Spare * spare);
+-      int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
+-                               int blockInNAND);
+-      int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
++        int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
++                                 int blockInNAND);
++        int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
++        int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev);
+ #ifdef CONFIG_YAFFS_YAFFS2
+-      int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
++        int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
+                                        int chunkInNAND, const __u8 * data,
+                                        const yaffs_ExtendedTags * tags);
+       int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
+@@ -583,25 +589,27 @@ struct yaffs_DeviceStruct {
+                                         yaffs_ExtendedTags * tags);
+       int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
+       int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
+-                             yaffs_BlockState * state, int *sequenceNumber);
++                             yaffs_BlockState * state, __u32 *sequenceNumber);
+ #endif
+       int isYaffs2;
+-
+-      /* The removeObjectCallback function must be supplied by OS flavours that
++      
++      /* The removeObjectCallback function must be supplied by OS flavours that 
+        * need it. The Linux kernel does not use this, but yaffs direct does use
+        * it to implement the faster readdir
+        */
+       void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
+-
++      
+       /* Callback to mark the superblock dirsty */
+       void (*markSuperBlockDirty)(void * superblock);
+-
++      
+       int wideTnodesDisabled; /* Set to disable wide tnodes */
+-
++      
++      YCHAR *pathDividers;    /* String of legal path dividers */
++      
+       /* End of stuff that must be set before initialisation. */
+-
++      
+       /* Checkpoint control. Can be set before or after initialisation */
+       __u8 skipCheckpointRead;
+       __u8 skipCheckpointWrite;
+@@ -610,34 +618,32 @@ struct yaffs_DeviceStruct {
+       __u16 chunkGroupBits;   /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
+       __u16 chunkGroupSize;   /* == 2^^chunkGroupBits */
+-
++      
+       /* Stuff to support wide tnodes */
+       __u32 tnodeWidth;
+       __u32 tnodeMask;
+-
+-      /* Stuff to support various file offses to chunk/offset translations */
+-      /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
+-      __u32 crumbMask;
+-      __u32 crumbShift;
+-      __u32 crumbsPerChunk;
+-
+-      /* Straight shifting for nDataBytesPerChunk being a power of 2 */
+-      __u32 chunkShift;
+-      __u32 chunkMask;
+-
++      
++      /* Stuff for figuring out file offset to chunk conversions */
++      __u32 chunkShift; /* Shift value */
++      __u32 chunkDiv;   /* Divisor after shifting: 1 for power-of-2 sizes */
++      __u32 chunkMask;  /* Mask to use for power-of-2 case */
++
++      /* Stuff to handle inband tags */
++      int inbandTags;
++      __u32 totalBytesPerChunk;
+ #ifdef __KERNEL__
+       struct semaphore sem;   /* Semaphore for waiting on erasure.*/
+       struct semaphore grossLock;     /* Gross locking semaphore */
+-      __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer
++      __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer 
+                                * at compile time so we have to allocate it.
+                                */
+       void (*putSuperFunc) (struct super_block * sb);
+ #endif
+       int isMounted;
+-
++      
+       int isCheckpointed;
+@@ -646,7 +652,7 @@ struct yaffs_DeviceStruct {
+       int internalEndBlock;
+       int blockOffset;
+       int chunkOffset;
+-
++      
+       /* Runtime checkpointing stuff */
+       int checkpointPageSequence;   /* running sequence number of checkpoint pages */
+@@ -662,13 +668,15 @@ struct yaffs_DeviceStruct {
+       int checkpointMaxBlocks;
+       __u32 checkpointSum;
+       __u32 checkpointXor;
+-
++      
++      int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */
++      
+       /* Block Info */
+       yaffs_BlockInfo *blockInfo;
+       __u8 *chunkBits;        /* bitmap of chunks in use */
+       unsigned blockInfoAlt:1;        /* was allocated using alternative strategy */
+       unsigned chunkBitsAlt:1;        /* was allocated using alternative strategy */
+-      int chunkBitmapStride;  /* Number of bytes of chunkBits per block.
++      int chunkBitmapStride;  /* Number of bytes of chunkBits per block. 
+                                * Must be consistent with nChunksPerBlock.
+                                */
+@@ -684,10 +692,14 @@ struct yaffs_DeviceStruct {
+       yaffs_TnodeList *allocatedTnodeList;
+       int isDoingGC;
++      int gcBlock;
++      int gcChunk;
+       int nObjectsCreated;
+       yaffs_Object *freeObjects;
+       int nFreeObjects;
++      
++      int nHardLinks;
+       yaffs_ObjectList *allocatedObjectList;
+@@ -716,7 +728,7 @@ struct yaffs_DeviceStruct {
+       int tagsEccUnfixed;
+       int nDeletions;
+       int nUnmarkedDeletions;
+-
++      
+       int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
+       /* Special directories */
+@@ -727,7 +739,7 @@ struct yaffs_DeviceStruct {
+        *      __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
+        *      yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
+        */
+-
++      
+       int bufferedBlock;      /* Which block is buffered here? */
+       int doingBufferedBlockRewrite;
+@@ -744,9 +756,11 @@ struct yaffs_DeviceStruct {
+       int nUnlinkedFiles;             /* Count of unlinked files. */
+       int nBackgroundDeletions;       /* Count of background deletions. */
+-
++      
++      /* Temporary buffer management */
+       yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
+       int maxTemp;
++      int tempInUse;
+       int unmanagedTempAllocations;
+       int unmanagedTempDeallocations;
+@@ -758,17 +772,17 @@ struct yaffs_DeviceStruct {
+ typedef struct yaffs_DeviceStruct yaffs_Device;
+-/* The static layout of bllock usage etc is stored in the super block header */
++/* The static layout of block usage etc is stored in the super block header */
+ typedef struct {
+         int StructType;
+-      int version;
++        int version;
+       int checkpointStartBlock;
+       int checkpointEndBlock;
+       int startBlock;
+       int endBlock;
+       int rfu[100];
+ } yaffs_SuperBlockHeader;
+-
++      
+ /* The CheckpointDevice structure holds the device information that changes at runtime and
+  * must be preserved over unmount/mount cycles.
+  */
+@@ -797,18 +811,6 @@ typedef struct {
+     __u32 head;
+ } yaffs_CheckpointValidity;
+-/* Function to manipulate block info */
+-static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
+-{
+-      if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
+-              T(YAFFS_TRACE_ERROR,
+-                (TSTR
+-                 ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
+-                 blk));
+-              YBUG();
+-      }
+-      return &dev->blockInfo[blk - dev->internalStartBlock];
+-}
+ /*----------------------- YAFFS Functions -----------------------*/
+@@ -834,13 +836,13 @@ int yaffs_GetAttributes(yaffs_Object * o
+ /* File operations */
+ int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
+-                         int nBytes);
++                           int nBytes);
+ int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
+-                        int nBytes, int writeThrough);
++                          int nBytes, int writeThrough);
+ int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
+ yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
+-                            __u32 mode, __u32 uid, __u32 gid);
++                              __u32 mode, __u32 uid, __u32 gid);
+ int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
+ /* Flushing and checkpointing */
+@@ -899,4 +901,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
+ int yaffs_CheckFF(__u8 * buffer, int nBytes);
+ void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
++__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
++void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo);
++
+ #endif
+--- a/fs/yaffs2/moduleconfig.h
++++ b/fs/yaffs2/moduleconfig.h
+@@ -54,11 +54,11 @@ that you need to continue to support.  N
+ older-style format.
+ Note: Use of this option generally requires that MTD's oob layout be
+ adjusted to use the older-style format.  See notes on tags formats and
+-MTD versions.
++MTD versions in yaffs_mtdif1.c.
+ */
+ /* Default: Not selected */
+ /* Meaning: Use older-style on-NAND data format with pageStatus byte */
+-#define CONFIG_YAFFS_9BYTE_TAGS
++//#define CONFIG_YAFFS_9BYTE_TAGS
+ #endif /* YAFFS_OUT_OF_TREE */
+--- a/fs/yaffs2/yaffs_mtdif1.h
++++ b/fs/yaffs2/yaffs_mtdif1.h
+@@ -23,6 +23,6 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
+ int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
+ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+-      yaffs_BlockState * state, int *sequenceNumber);
++      yaffs_BlockState * state, __u32 *sequenceNumber);
+ #endif
+--- a/fs/yaffs2/yaffs_mtdif2.h
++++ b/fs/yaffs2/yaffs_mtdif2.h
+@@ -24,6 +24,6 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
+                                      __u8 * data, yaffs_ExtendedTags * tags);
+ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
+ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+-                          yaffs_BlockState * state, int *sequenceNumber);
++                          yaffs_BlockState * state, __u32 *sequenceNumber);
+ #endif
+--- a/fs/yaffs2/yaffs_checkptrw.c
++++ b/fs/yaffs2/yaffs_checkptrw.c
+@@ -12,11 +12,11 @@
+  */
+ const char *yaffs_checkptrw_c_version =
+-    "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $";
++    "$Id: yaffs_checkptrw.c,v 1.17 2008-08-12 22:51:57 charles Exp $";
+ #include "yaffs_checkptrw.h"
+-
++#include "yaffs_getblockinfo.h"
+ static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
+ {
+@@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
+               return 0;
+       if(!dev->checkpointBuffer)
+-              dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
++              dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
+       if(!dev->checkpointBuffer)
+               return 0;
+@@ -324,6 +324,7 @@ int yaffs_CheckpointRead(yaffs_Device *d
+                                                             &tags);
+                               if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
++                                 tags.eccResult > YAFFS_ECC_RESULT_FIXED ||
+                                  tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
+                                  ok = 0;
+--- a/fs/yaffs2/yaffs_tagscompat.c
++++ b/fs/yaffs2/yaffs_tagscompat.c
+@@ -14,6 +14,7 @@
+ #include "yaffs_guts.h"
+ #include "yaffs_tagscompat.h"
+ #include "yaffs_ecc.h"
++#include "yaffs_getblockinfo.h"
+ static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
+ #ifdef NOTYET
+@@ -252,6 +253,9 @@ static int yaffs_ReadChunkFromNAND(struc
+               /* Must allocate enough memory for spare+2*sizeof(int) */
+               /* for ecc results from device. */
+               struct yaffs_NANDSpare nspare;
++              
++              memset(&nspare,0,sizeof(nspare));
++              
+               retVal =
+                   dev->readChunkFromNAND(dev, chunkInNAND, data,
+                                          (yaffs_Spare *) & nspare);
+@@ -336,7 +340,7 @@ static void yaffs_HandleReadDataError(ya
+       int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
+       /* Mark the block for retirement */
+-      yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
++      yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
+       T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+         (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
+@@ -414,7 +418,16 @@ int yaffs_TagsCompatabilityWriteChunkWit
+       } else {
+               tags.objectId = eTags->objectId;
+               tags.chunkId = eTags->chunkId;
+-              tags.byteCount = eTags->byteCount;
++
++              tags.byteCountLSB = eTags->byteCount & 0x3ff;
++              
++              if(dev->nDataBytesPerChunk >= 1024){
++                      tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
++              } else {
++                      tags.byteCountMSB = 3;
++              }
++              
++
+               tags.serialNumber = eTags->serialNumber;
+               if (!dev->useNANDECC && data) {
+@@ -435,10 +448,10 @@ int yaffs_TagsCompatabilityReadChunkWith
+       yaffs_Spare spare;
+       yaffs_Tags tags;
+-      yaffs_ECCResult eccResult;
++      yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;
+       static yaffs_Spare spareFF;
+-      static int init;
++      static int init = 0;
+       if (!init) {
+               memset(&spareFF, 0xFF, sizeof(spareFF));
+@@ -466,7 +479,11 @@ int yaffs_TagsCompatabilityReadChunkWith
+                               eTags->objectId = tags.objectId;
+                               eTags->chunkId = tags.chunkId;
+-                              eTags->byteCount = tags.byteCount;
++                              eTags->byteCount = tags.byteCountLSB;
++
++                              if(dev->nDataBytesPerChunk >= 1024)
++                                      eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
++
+                               eTags->serialNumber = tags.serialNumber;
+                       }
+               }
+@@ -497,9 +514,9 @@ int yaffs_TagsCompatabilityMarkNANDBlock
+ }
+ int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
+-                                        int blockNo, yaffs_BlockState *
+-                                        state,
+-                                        int *sequenceNumber)
++                                        int blockNo,
++                                        yaffs_BlockState *state,
++                                        __u32 *sequenceNumber)
+ {
+       yaffs_Spare spare0, spare1;
+--- a/fs/yaffs2/yaffs_mtdif.c
++++ b/fs/yaffs2/yaffs_mtdif.c
+@@ -12,7 +12,7 @@
+  */
+ const char *yaffs_mtdif_c_version =
+-    "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $";
++    "$Id: yaffs_mtdif.c,v 1.21 2007-12-13 15:35:18 wookey Exp $";
+ #include "yportenv.h"
+@@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version =
+ #include "linux/time.h"
+ #include "linux/mtd/nand.h"
+-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
++#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
+ static struct nand_oobinfo yaffs_oobinfo = {
+       .useecc = 1,
+       .eccbytes = 6,
+@@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccin
+ };
+ #endif
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+ static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
+ {
+       oob[0] = spare->tagByte0;
+@@ -75,14 +75,14 @@ int nandmtd_WriteChunkToNAND(yaffs_Devic
+                            const __u8 * data, const yaffs_Spare * spare)
+ {
+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+       struct mtd_oob_ops ops;
+ #endif
+       size_t dummy;
+       int retval = 0;
+       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+       __u8 spareAsBytes[8]; /* OOB */
+       if (data && !spare)
+@@ -139,14 +139,14 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi
+                             yaffs_Spare * spare)
+ {
+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+       struct mtd_oob_ops ops;
+ #endif
+       size_t dummy;
+       int retval = 0;
+       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
++#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
+       __u8 spareAsBytes[8]; /* OOB */
+       if (data && !spare)
+--- a/fs/yaffs2/yaffs_nandemul2k.h
++++ b/fs/yaffs2/yaffs_nandemul2k.h
+@@ -22,13 +22,13 @@
+ int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
+                                       int chunkInNAND, const __u8 * data,
+-                                      yaffs_ExtendedTags * tags);
++                                      const yaffs_ExtendedTags * tags);
+ int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
+                                        int chunkInNAND, __u8 * data,
+                                        yaffs_ExtendedTags * tags);
+ int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
+ int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
+-                            yaffs_BlockState * state, int *sequenceNumber);
++                            yaffs_BlockState * state, __u32 *sequenceNumber);
+ int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
+                               int blockInNAND);
+ int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);
diff --git a/target/linux/generic-2.6/patches-2.6.28/512-yaffs_2.6.25_fix.patch b/target/linux/generic-2.6/patches-2.6.28/512-yaffs_2.6.25_fix.patch
deleted file mode 100644 (file)
index c127336..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
---- a/fs/yaffs2/yaffs_fs.c
-+++ b/fs/yaffs2/yaffs_fs.c
-@@ -181,7 +181,13 @@ static int yaffs_statfs(struct super_blo
- #else
- static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
- #endif
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
-+static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino);
-+#else
- static void yaffs_read_inode(struct inode *inode);
-+#endif
-+
- static void yaffs_put_inode(struct inode *inode);
- static void yaffs_delete_inode(struct inode *);
-@@ -284,7 +290,9 @@ static struct file_operations yaffs_dir_
- static struct super_operations yaffs_super_ops = {
-       .statfs = yaffs_statfs,
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
-       .read_inode = yaffs_read_inode,
-+#endif
-       .put_inode = yaffs_put_inode,
-       .put_super = yaffs_put_super,
-       .delete_inode = yaffs_delete_inode,
-@@ -844,11 +852,17 @@ struct inode *yaffs_get_inode(struct sup
-       T(YAFFS_TRACE_OS,
-         (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
-+      inode = yaffs_iget(sb, obj->objectId);
-+      if (IS_ERR(inode))
-+              return NULL;
-+#else
-       inode = iget(sb, obj->objectId);
-       /* NB Side effect: iget calls back to yaffs_read_inode(). */
-       /* iget also increments the inode's i_count */
-       /* NB You can't be holding grossLock or deadlock will happen! */
-+#endif
-       return inode;
- }
-@@ -1427,6 +1441,39 @@ static int yaffs_sync_fs(struct super_bl
- }
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25))
-+static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
-+{
-+      yaffs_Object *obj;
-+      yaffs_Device *dev = yaffs_SuperToDevice(sb);
-+      struct inode *inode;
-+
-+      T(YAFFS_TRACE_OS,
-+        (KERN_DEBUG "yaffs_iget for %lu\n", ino));
-+
-+      inode = iget_locked(sb, ino);
-+      if (!inode)
-+              return ERR_PTR(-ENOMEM);
-+      if (!(inode->i_state & I_NEW))
-+              return inode;
-+
-+      /* NB This is called as a side effect of other functions, but
-+       * we had to release the lock to prevent deadlocks, so
-+       * need to lock again.
-+       */
-+
-+      yaffs_GrossLock(dev);
-+
-+      obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
-+
-+      yaffs_FillInodeFromObject(inode, obj);
-+
-+      yaffs_GrossUnlock(dev);
-+
-+      unlock_new_inode(inode);
-+      return inode;
-+}
-+#else
- static void yaffs_read_inode(struct inode *inode)
- {
-       /* NB This is called as a side effect of other functions, but
-@@ -1448,6 +1495,7 @@ static void yaffs_read_inode(struct inod
-       yaffs_GrossUnlock(dev);
- }
-+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)) */
- static LIST_HEAD(yaffs_dev_list);
diff --git a/target/linux/generic-2.6/patches-2.6.28/513-yaffs_2.6.26_fix.patch b/target/linux/generic-2.6/patches-2.6.28/513-yaffs_2.6.26_fix.patch
deleted file mode 100644 (file)
index 1159454..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
---- a/fs/yaffs2/yaffs_fs.c
-+++ b/fs/yaffs2/yaffs_fs.c
-@@ -76,6 +76,12 @@ extern const char *yaffs_guts_c_version;
- #endif
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
-+#define YPROC_ROOT    &proc_root
-+#else
-+#define YPROC_ROOT    NULL
-+#endif
-+
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
- #define WRITE_SIZE_STR "writesize"
- #define WRITE_SIZE(mtd) (mtd)->writesize
-@@ -189,7 +195,9 @@ static void yaffs_read_inode(struct inod
- #endif
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
- static void yaffs_put_inode(struct inode *inode);
-+#endif
- static void yaffs_delete_inode(struct inode *);
- static void yaffs_clear_inode(struct inode *);
-@@ -293,7 +301,9 @@ static struct super_operations yaffs_sup
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
-       .read_inode = yaffs_read_inode,
- #endif
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
-       .put_inode = yaffs_put_inode,
-+#endif
-       .put_super = yaffs_put_super,
-       .delete_inode = yaffs_delete_inode,
-       .clear_inode = yaffs_clear_inode,
-@@ -437,6 +447,7 @@ static struct dentry *yaffs_lookup(struc
- }
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
- /* For now put inode is just for debugging
-  * Put inode is called when the inode **structure** is put.
-  */
-@@ -447,6 +458,7 @@ static void yaffs_put_inode(struct inode
-          atomic_read(&inode->i_count)));
- }
-+#endif
- /* clear is called to tell the fs to release any per-inode data it holds */
- static void yaffs_clear_inode(struct inode *inode)
-@@ -2279,7 +2291,7 @@ static int __init init_yaffs_fs(void)
-       /* Install the proc_fs entry */
-       my_proc_entry = create_proc_entry("yaffs",
-                                              S_IRUGO | S_IFREG,
--                                             &proc_root);
-+                                             YPROC_ROOT);
-       if (my_proc_entry) {
-               my_proc_entry->write_proc = yaffs_proc_write;
-@@ -2325,7 +2337,7 @@ static void __exit exit_yaffs_fs(void)
-       T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__
-                              " removing. \n"));
--      remove_proc_entry("yaffs", &proc_root);
-+      remove_proc_entry("yaffs", YPROC_ROOT);
-       fsinst = fs_to_install;
diff --git a/target/linux/generic-2.6/patches-2.6.28/514-yaffs_2.6.28_fixes.patch b/target/linux/generic-2.6/patches-2.6.28/514-yaffs_2.6.28_fixes.patch
deleted file mode 100644 (file)
index 012ba04..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
---- a/fs/yaffs2/yaffs_fs.c
-+++ b/fs/yaffs2/yaffs_fs.c
-@@ -207,10 +207,20 @@ static int yaffs_writepage(struct page *
- #else
- static int yaffs_writepage(struct page *page);
- #endif
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
-+static int yaffs_write_begin(struct file *f, struct address_space *mapping,
-+                            loff_t pos, unsigned len, unsigned flags,
-+                            struct page **pagep, void **fsdata);
-+static int yaffs_write_end(struct file *f, struct address_space *mapping,
-+                          loff_t pos, unsigned len, unsigned copied,
-+                          struct page *pg, void *fsdata);
-+#else
- static int yaffs_prepare_write(struct file *f, struct page *pg,
-                              unsigned offset, unsigned to);
- static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
-                             unsigned to);
-+#endif
- static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
-                         int buflen);
-@@ -223,8 +233,13 @@ static int yaffs_follow_link(struct dent
- static struct address_space_operations yaffs_file_address_operations = {
-       .readpage = yaffs_readpage,
-       .writepage = yaffs_writepage,
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
-+      .write_begin = yaffs_write_begin,
-+      .write_end = yaffs_write_end,
-+#else
-       .prepare_write = yaffs_prepare_write,
-       .commit_write = yaffs_commit_write,
-+#endif
- };
- #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
-@@ -687,6 +702,74 @@ static int yaffs_writepage(struct page *
-       return (nWritten == nBytes) ? 0 : -ENOSPC;
- }
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
-+static int yaffs_write_begin(struct file *f, struct address_space *mapping,
-+                            loff_t pos, unsigned len, unsigned flags,
-+                            struct page **pagep, void **fsdata)
-+{
-+      struct page *pg;
-+      pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-+      int ret = 0;
-+
-+      pg = __grab_cache_page(mapping, index);
-+      if (!pg)
-+              return -ENOMEM;
-+
-+      *pagep = pg;
-+
-+      T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_begin\n"));
-+      if (!Page_Uptodate(pg)) {
-+              ret = yaffs_readpage_nolock(f, pg);
-+              if (ret)
-+                      goto err_unlock;
-+      }
-+
-+      T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_begin\n"));
-+      return 0;
-+
-+ err_unlock:
-+      unlock_page(pg);
-+      page_cache_release(pg);
-+      return ret;
-+}
-+
-+static int yaffs_write_end(struct file *f, struct address_space *mapping,
-+                          loff_t pos, unsigned len, unsigned copied,
-+                          struct page *pg, void *fsdata)
-+{
-+      void *addr = page_address(pg) + (pos & (PAGE_CACHE_SIZE - 1));
-+      loff_t pos2;
-+      int nBytes = copied;
-+      int nWritten;
-+
-+      T(YAFFS_TRACE_OS,
-+       (KERN_DEBUG "yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned)addr,
-+       (unsigned)pos, nBytes));
-+
-+      pos2 = pos;
-+      nWritten = yaffs_file_write(f, addr, nBytes, &pos2);
-+
-+      if (nWritten != nBytes) {
-+              T(YAFFS_TRACE_OS,
-+               (KERN_DEBUG
-+               "yaffs_write_end not same size nWritten %d  nBytes %d\n",
-+                nWritten, nBytes));
-+              SetPageError(pg);
-+              ClearPageUptodate(pg);
-+      } else {
-+              SetPageUptodate(pg);
-+      }
-+
-+      T(YAFFS_TRACE_OS,
-+       (KERN_DEBUG "yaffs_write_end returning %d\n",
-+       nWritten == nBytes ? nWritten : 0));
-+
-+      unlock_page(pg);
-+      page_cache_release(pg);
-+
-+      return (nWritten == nBytes) ? nWritten : 0;
-+}
-+#else
- static int yaffs_prepare_write(struct file *f, struct page *pg,
-                              unsigned offset, unsigned to)
- {
-@@ -735,6 +818,7 @@ static int yaffs_commit_write(struct fil
-       return nWritten == nBytes ? 0 : nWritten;
- }
-+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) */
- static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
- {