yaffs Refactor yaffs1 and yaffs2 specific code. WIP
[yaffs2.git] / yaffs_guts.c
index 2ab6edfd197b1ea3d5285032ad00848924a25226..58e9442cc688c0663deff80eea0352f51c974850 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  *
- * Copyright (C) 2002-2007 Aleph One Ltd.
+ * Copyright (C) 2002-2010 Aleph One Ltd.
  *   for Toby Churchill Ltd and Brightstar Engineering
  *
  * Created by Charles Manning <charles@aleph1.co.uk>
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-const char *yaffs_guts_c_version =
-    "$Id: yaffs_guts.c,v 1.120 2010-03-15 23:10:34 charles Exp $";
-
 #include "yportenv.h"
 #include "yaffs_trace.h"
 
@@ -23,9 +19,8 @@ const char *yaffs_guts_c_version =
 #include "yaffs_getblockinfo.h"
 
 #include "yaffs_tagscompat.h"
-#ifndef CONFIG_YAFFS_USE_OWN_SORT
 #include "yaffs_qsort.h"
-#endif
+
 #include "yaffs_nand.h"
 
 #include "yaffs_checkptrw.h"
@@ -33,14 +28,34 @@ const char *yaffs_guts_c_version =
 #include "yaffs_nand.h"
 #include "yaffs_packedtags2.h"
 
+#include "yaffs_nameval.h"
+#include "yaffs_allocator.h"
 
 /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
 #define YAFFS_GC_GOOD_ENOUGH 2
 #define YAFFS_GC_PASSIVE_THRESHOLD 4
+
 #define YAFFS_SMALL_HOLE_THRESHOLD 3
 
+/*
+ * Checkpoints are really no benefit on very small partitions.
+ *
+ * To save space on small partitions don't bother with checkpoints unless
+ * the partition is at least this big.
+ */
+#define YAFFS_CHECKPOINT_MIN_BLOCKS 60
+
 #include "yaffs_ecc.h"
 
+/* Private structure for doing xattr modifications */
+typedef struct {
+       int set; /* If 0 then this is a deletion */
+       const char *name;
+       const void *data;
+       int size;
+       int flags;
+       int result;
+} yaffs_XAttrMod;
 
 /* Robustification (if it ever comes about...) */
 static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND);
@@ -71,11 +86,11 @@ static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number,
 static void yaffs_AddObjectToDirectory(yaffs_Object *directory,
                                yaffs_Object *obj);
 static int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name,
-                               int force, int isShrink, int shadows);
+                               int force, int isShrink, int shadows, yaffs_XAttrMod *xop);
+static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod);
+
 static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);
 static int yaffs_CheckStructures(void);
-static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level,
-                       int chunkOffset, int *limit);
 static int yaffs_DoGenericObjectDeletion(yaffs_Object *in);
 
 static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev, int blockNo);
@@ -106,7 +121,7 @@ static int yaffs_CheckFileSanity(yaffs_Object *in);
 static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in);
 static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId);
 
-static void yaffs_InvalidateCheckpoint(yaffs_Device *dev);
+static void yaffs2_InvalidateCheckpoint(yaffs_Device *dev);
 
 static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode,
                                yaffs_ExtendedTags *tags);
@@ -117,7 +132,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev,
                                        yaffs_FileStructure *fStruct,
                                        __u32 chunkId);
 
-static int yaffs_HandleHole(yaffs_Object *obj, loff_t newSize);
+static int yaffs2_HandleHole(yaffs_Object *obj, loff_t newSize);
 static void yaffs_SkipRestOfBlock(yaffs_Device *dev);
 static int yaffs_VerifyChunkWritten(yaffs_Device *dev,
                                        int chunkInNAND,
@@ -183,7 +198,7 @@ static __u32 ShiftsGE(__u32 x)
 
 static __u32 Shifts(__u32 x)
 {
-       int nShifts;
+       __u32 nShifts;
 
        nShifts =  0;
 
@@ -437,6 +452,17 @@ static const char *blockStateName[] = {
 "Dead"
 };
 
+static void yaffs2_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n)
+{
+       if (!dev->param.isYaffs2)
+               return;
+
+       if((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_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n)
 {
        int actuallyUsed;
@@ -477,13 +503,12 @@ static void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n)
        /* Check that the sequence number is valid.
         * Ten million is legal, but is very unlikely
         */
-       if (dev->param.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));
+
+        yaffs2_VerifyBlock(dev,bi,n);
 }
 
+
+
 static void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi,
                int n)
 {
@@ -610,7 +635,8 @@ static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh,
 }
 
 
-
+#if 0
+/* Not being used, but don't want to throw away yet */
 static int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn,
                                        __u32 level, int chunkOffset)
 {
@@ -656,6 +682,7 @@ static int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn,
 
 }
 
+#endif
 
 static void yaffs_VerifyFile(yaffs_Object *obj)
 {
@@ -958,7 +985,7 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
        int writeOk = 0;
        int chunk;
 
-       yaffs_InvalidateCheckpoint(dev);
+       yaffs2_InvalidateCheckpoint(dev);
 
        do {
                yaffs_BlockInfo *bi = 0;
@@ -1056,11 +1083,11 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
  * Oldest Dirty Sequence Number handling.
  */
  
-/* yaffs_CalcOldestDirtySequence()
- * yaffs_FindOldestDirtySequence()
+/* yaffs2_CalcOldestDirtySequence()
+ * yaffs2_FindOldestDirtySequence()
  * Calculate the oldest dirty sequence number if we don't know it.
  */
-static void yaffs_CalcOldestDirtySequence(yaffs_Device *dev)
+static void yaffs2_CalcOldestDirtySequence(yaffs_Device *dev)
 {
        int i;
        unsigned seq;
@@ -1091,10 +1118,13 @@ static void yaffs_CalcOldestDirtySequence(yaffs_Device *dev)
 }
 
 
-static void yaffs_FindOldestDirtySequence(yaffs_Device *dev)
+static void yaffs2_FindOldestDirtySequence(yaffs_Device *dev)
 {
-       if(dev->param.isYaffs2 && !dev->oldestDirtySequence)
-               yaffs_CalcOldestDirtySequence(dev);
+       if(!dev->param.isYaffs2)
+               return;
+
+       if(!dev->oldestDirtySequence)
+               yaffs2_CalcOldestDirtySequence(dev);
 }
 
 /*
@@ -1103,7 +1133,7 @@ static void yaffs_FindOldestDirtySequence(yaffs_Device *dev)
  * becomes invalid). If the value matches the oldest then we clear 
  * dev->oldestDirtySequence to force its recomputation.
  */
-static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi)
+static void yaffs2_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *bi)
 {
 
        if(!dev->param.isYaffs2)
@@ -1116,13 +1146,16 @@ static void yaffs_ClearOldestDirtySequence(yaffs_Device *dev, yaffs_BlockInfo *b
 }
 
 /*
- * yaffs_UpdateOldestDirtySequence()
+ * yaffs2_UpdateOldestDirtySequence()
  * Update the oldest dirty sequence number whenever we dirty a block.
  * Only do this if the oldestDirtySequence is actually being tracked.
  */
-static void yaffs_UpdateOldestDirtySequence(yaffs_Device *dev, unsigned blockNo, yaffs_BlockInfo *bi)
+static void yaffs2_UpdateOldestDirtySequence(yaffs_Device *dev, unsigned blockNo, yaffs_BlockInfo *bi)
 {
-       if(dev->param.isYaffs2 && dev->oldestDirtySequence){
+       if(!dev->param.isYaffs2)
+               return;
+
+       if(dev->oldestDirtySequence){
                if(dev->oldestDirtySequence > bi->sequenceNumber){
                        dev->oldestDirtySequence = bi->sequenceNumber;
                        dev->oldestDirtyBlock = blockNo;
@@ -1138,9 +1171,9 @@ static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND)
 {
        yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
 
-       yaffs_InvalidateCheckpoint(dev);
+       yaffs2_InvalidateCheckpoint(dev);
        
-       yaffs_ClearOldestDirtySequence(dev,bi);
+       yaffs2_ClearOldestDirtySequence(dev,bi);
 
        if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) {
                if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) {
@@ -1274,194 +1307,33 @@ static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name)
  * in the tnode.
  */
 
-/* yaffs_CreateTnodes creates a bunch more tnodes and
- * adds them to the tnode free list.
- * Don't use this function directly
- */
-static Y_INLINE int yaffs_CalcTnodeSize(yaffs_Device *dev)
-{
-       int tnodeSize;
-       /* 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);
-       return tnodeSize;
-}
 
-static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)
+static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
 {
-       int i;
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
-       yaffs_Tnode *newTnodes;
-       __u8 *mem;
-       yaffs_Tnode *curr;
-       yaffs_Tnode *next;
-       yaffs_TnodeList *tnl;
-
-       if (nTnodes < 1)
-               return YAFFS_OK;
-
-
-       /* make these things */
-
-       newTnodes = YMALLOC(nTnodes * tnodeSize);
-       mem = (__u8 *)newTnodes;
-
-       if (!newTnodes) {
-               T(YAFFS_TRACE_ERROR,
-                       (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
-               return YAFFS_FAIL;
-       }
-
-       /* Hook them into the free list */
-#if 0
-       for (i = 0; i < nTnodes - 1; i++) {
-               newTnodes[i].internal[0] = &newTnodes[i + 1];
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-               newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
-#endif
-       }
-
-       newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-       newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
-#endif
-       dev->freeTnodes = newTnodes;
-#else
-       /* New hookup for wide tnodes */
-       for (i = 0; i < nTnodes - 1; i++) {
-               curr = (yaffs_Tnode *) &mem[i * tnodeSize];
-               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;
-
-#endif
-
-
-       dev->nFreeTnodes += nTnodes;
-       dev->nTnodesCreated += nTnodes;
-
-       /* Now add this bunch of tnodes to a list for freeing up.
-        * 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,
-                 (TSTR
-                  ("yaffs: Could not add tnodes to management list" TENDSTR)));
-                  return YAFFS_FAIL;
-       } else {
-               tnl->tnodes = newTnodes;
-               tnl->next = dev->allocatedTnodeList;
-               dev->allocatedTnodeList = tnl;
+       yaffs_Tnode *tn = yaffs_AllocateRawTnode(dev);
+       if (tn){
+               memset(tn, 0, dev->tnodeSize);
+               dev->nTnodes++;
        }
 
-       T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
-
-       return YAFFS_OK;
-}
-
-/* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */
-
-static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device *dev)
-{
-       yaffs_Tnode *tn = NULL;
-
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-       tn = YMALLOC(yaffs_CalcTnodeSize(dev));
-       if(tn)
-               dev->nTnodesCreated++;
-#else
-       /* If there are none left make more */
-       if (!dev->freeTnodes)
-               yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
-
-       if (dev->freeTnodes) {
-               tn = dev->freeTnodes;
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-               if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {
-                       /* Hoosterman, this thing looks like it isn't in the list */
-                       T(YAFFS_TRACE_ALWAYS,
-                         (TSTR("yaffs: Tnode list bug 1" TENDSTR)));
-               }
-#endif
-               dev->freeTnodes = dev->freeTnodes->internal[0];
-               dev->nFreeTnodes--;
-       }
-#endif
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 
        return tn;
 }
 
-static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
-{
-       yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
-
-       if (tn)
-               memset(tn, 0, tnodeSize);
-
-       return tn;
-}
-
 /* FreeTnode frees up a tnode and puts it back on the free list */
 static void yaffs_FreeTnode(yaffs_Device *dev, yaffs_Tnode *tn)
 {
-       if (tn) {
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-               YFREE(tn);
-               dev->nTnodesCreated--;
-#else
-#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
-               if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {
-                       /* Hoosterman, this thing looks like it is already in the list */
-                       T(YAFFS_TRACE_ALWAYS,
-                         (TSTR("yaffs: Tnode list bug 2" TENDSTR)));
-               }
-               tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
-#endif
-               tn->internal[0] = dev->freeTnodes;
-               dev->freeTnodes = tn;
-               dev->nFreeTnodes++;
-#endif
-       }
+       yaffs_FreeRawTnode(dev,tn);
+       dev->nTnodes--;
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 }
 
-static void yaffs_DeinitialiseTnodes(yaffs_Device *dev)
-{
-       /* Free the list of allocated tnodes */
-       yaffs_TnodeList *tmp;
-
-       while (dev->allocatedTnodeList) {
-               tmp = dev->allocatedTnodeList->next;
-
-               YFREE(dev->allocatedTnodeList->tnodes);
-               YFREE(dev->allocatedTnodeList);
-               dev->allocatedTnodeList = tmp;
-
-       }
-
-       dev->freeTnodes = NULL;
-       dev->nFreeTnodes = 0;
-       dev->nTnodesCreated = 0;
-}
-
-static void yaffs_InitialiseTnodes(yaffs_Device *dev)
+static void yaffs_DeinitialiseTnodesAndObjects(yaffs_Device *dev)
 {
-       dev->allocatedTnodeList = NULL;
-       dev->freeTnodes = NULL;
-       dev->nFreeTnodes = 0;
-       dev->nTnodesCreated = 0;
+       yaffs_DeinitialiseRawTnodesAndObjects(dev);
+       dev->nObjects = 0;
+       dev->nTnodes = 0;
 }
 
 
@@ -1708,9 +1580,10 @@ static int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk,
        return -1;
 }
 
-
+#if 0
+/* Experimental code not being used yet. Might speed up file deletion */
 /* DeleteWorker scans backwards through the tnode tree and deletes all the
- * chunks and tnodes in the file
+ * chunks and tnodes in the file.
  * Returns 1 if the tree was deleted.
  * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
  */
@@ -1802,6 +1675,8 @@ static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level,
 
 }
 
+#endif
+
 static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk)
 {
        yaffs_BlockInfo *theBlock;
@@ -1814,7 +1689,7 @@ static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk)
        if (theBlock) {
                theBlock->softDeletions++;
                dev->nFreeChunks++;
-               yaffs_UpdateOldestDirtySequence(dev, blockNo, theBlock);
+               yaffs2_UpdateOldestDirtySequence(dev, blockNo, theBlock);
        }
 }
 
@@ -1942,7 +1817,7 @@ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn,
                                        hasData++;
                        }
                } else {
-                       int tnodeSize_u32 = yaffs_CalcTnodeSize(dev)/sizeof(__u32);
+                       int tnodeSize_u32 = dev->tnodeSize/sizeof(__u32);
                        __u32 *map = (__u32 *)tn;
 
                         for(i = 0; !hasData && i < tnodeSize_u32; i++){
@@ -2007,96 +1882,32 @@ static int yaffs_PruneFileStructure(yaffs_Device *dev,
 
 /*-------------------- End of File Structure functions.-------------------*/
 
-/* yaffs_CreateFreeObjects creates a bunch more objects and
- * adds them to the object free list.
- */
-static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
-{
-       int i;
-       yaffs_Object *newObjects;
-       yaffs_ObjectList *list;
-
-       if (nObjects < 1)
-               return YAFFS_OK;
-
-       /* make these things */
-       newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
-       list = YMALLOC(sizeof(yaffs_ObjectList));
-
-       if (!newObjects || !list) {
-               if (newObjects){
-                       YFREE(newObjects);
-                       newObjects = NULL;
-               }
-               if (list){
-                       YFREE(list);
-                       list = NULL;
-               }
-               T(YAFFS_TRACE_ALLOCATE,
-                 (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]);
-       }
-
-       newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
-       dev->freeObjects = newObjects;
-       dev->nFreeObjects += nObjects;
-       dev->nObjectsCreated += nObjects;
-
-       /* Now add this bunch of Objects to a list for freeing up. */
-
-       list->objects = newObjects;
-       list->next = dev->allocatedObjectList;
-       dev->allocatedObjectList = list;
-
-       return YAFFS_OK;
-}
-
 
 /* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */
 static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)
 {
-       yaffs_Object *tn = NULL;
+       yaffs_Object *obj = yaffs_AllocateRawObject(dev);
 
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-       tn = YMALLOC(sizeof(yaffs_Object));
-       if(tn)
-               dev->nObjectsCreated++;
-#else
-       /* If there are none left make more */
-       if (!dev->freeObjects)
-               yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
+       if (obj) {
+               dev->nObjects++;
 
-       if (dev->freeObjects) {
-               tn = dev->freeObjects;
-               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;
+               memset(obj, 0, sizeof(yaffs_Object));
+               obj->beingCreated = 1;
 
-               tn->myDev = dev;
-               tn->hdrChunk = 0;
-               tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
-               YINIT_LIST_HEAD(&(tn->hardLinks));
-               YINIT_LIST_HEAD(&(tn->hashLink));
-               YINIT_LIST_HEAD(&tn->siblings);
+               obj->myDev = dev;
+               obj->hdrChunk = 0;
+               obj->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
+               YINIT_LIST_HEAD(&(obj->hardLinks));
+               YINIT_LIST_HEAD(&(obj->hashLink));
+               YINIT_LIST_HEAD(&obj->siblings);
 
 
                /* Now make the directory sane */
                if (dev->rootDir) {
-                       tn->parent = dev->rootDir;
-                       ylist_add(&(tn->siblings), &dev->rootDir->variant.directoryVariant.children);
+                       obj->parent = dev->rootDir;
+                       ylist_add(&(obj->siblings), &dev->rootDir->variant.directoryVariant.children);
                }
 
                /* Add it to the lost and found directory.
@@ -2104,14 +1915,14 @@ static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)
                 * check if lostNFound exists first
                 */
                if (dev->lostNFoundDir)
-                       yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
+                       yaffs_AddObjectToDirectory(dev->lostNFoundDir, obj);
 
-               tn->beingCreated = 0;
+               obj->beingCreated = 0;
        }
 
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 
-       return tn;
+       return obj;
 }
 
 static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number,
@@ -2135,54 +1946,46 @@ static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number,
 
 }
 
-static void yaffs_UnhashObject(yaffs_Object *tn)
+static void yaffs_UnhashObject(yaffs_Object *obj)
 {
        int bucket;
-       yaffs_Device *dev = tn->myDev;
+       yaffs_Device *dev = obj->myDev;
 
        /* 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);
+       if (!ylist_empty(&obj->hashLink)) {
+               ylist_del_init(&obj->hashLink);
+               bucket = yaffs_HashFunction(obj->objectId);
                dev->objectBucket[bucket].count--;
        }
 }
 
 /*  FreeObject frees up a Object and puts it back on the free list */
-static void yaffs_FreeObject(yaffs_Object *tn)
+static void yaffs_FreeObject(yaffs_Object *obj)
 {
-       yaffs_Device *dev = tn->myDev;
+       yaffs_Device *dev = obj->myDev;
 
-       T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), tn, tn->myInode));
+       T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), obj, obj->myInode));
 
-       if (!tn)
+       if (!obj)
                YBUG();
-       if (tn->parent)
+       if (obj->parent)
                YBUG();
-       if (!ylist_empty(&tn->siblings))
+       if (!ylist_empty(&obj->siblings))
                YBUG();
 
 
-       if (tn->myInode) {
+       if (obj->myInode) {
                /* We're still hooked up to a cached inode.
                 * Don't delete now, but mark for later deletion
                 */
-               tn->deferedFree = 1;
+               obj->deferedFree = 1;
                return;
        }
 
-       yaffs_UnhashObject(tn);
+       yaffs_UnhashObject(obj);
 
-#ifdef CONFIG_YAFFS_VALGRIND_TEST
-       YFREE(tn);
-       dev->nObjectsCreated--;
-       tn = NULL;
-#else
-       /* Link into the free list. */
-       tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
-       dev->freeObjects = tn;
-       dev->nFreeObjects++;
-#endif
+       yaffs_FreeRawObject(dev,obj);
+       dev->nObjects--;
        dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
 }
 
@@ -2193,33 +1996,14 @@ void yaffs_HandleDeferedFree(yaffs_Object *obj)
                yaffs_FreeObject(obj);
 }
 
-
-static void yaffs_DeinitialiseObjects(yaffs_Device *dev)
-{
-       /* Free the list of allocated Objects */
-
-       yaffs_ObjectList *tmp;
-
-       while (dev->allocatedObjectList) {
-               tmp = dev->allocatedObjectList->next;
-               YFREE(dev->allocatedObjectList->objects);
-               YFREE(dev->allocatedObjectList);
-
-               dev->allocatedObjectList = tmp;
-       }
-
-       dev->freeObjects = NULL;
-       dev->nFreeObjects = 0;
-       dev->nObjectsCreated = 0;
-}
-
-static void yaffs_InitialiseObjects(yaffs_Device *dev)
+static void yaffs_InitialiseTnodesAndObjects(yaffs_Device *dev)
 {
        int i;
 
-       dev->allocatedObjectList = NULL;
-       dev->freeObjects = NULL;
-       dev->nFreeObjects = 0;
+       dev->nObjects = 0;
+       dev->nTnodes = 0;
+
+       yaffs_InitialiseRawTnodesAndObjects(dev);
 
        for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
                YINIT_LIST_HEAD(&dev->objectBucket[i].list);
@@ -2511,7 +2295,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
                        break;
                }
 
-               if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) {
+               if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0, NULL) < 0) {
                        /* Could not create the object header, fail the creation */
                        yaffs_DeleteObject(in);
                        in = NULL;
@@ -2619,7 +2403,7 @@ static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir,
                        obj->unlinked = 1;
 
                /* If it is a deletion then we mark it as a shrink for gc purposes. */
-               if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows) >= 0)
+               if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows, NULL) >= 0)
                        return YAFFS_OK;
        }
 
@@ -2752,7 +2536,7 @@ static void yaffs_DeinitialiseBlocks(yaffs_Device *dev)
        dev->chunkBits = NULL;
 }
 
-static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
+static int yaffs2_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
                                        yaffs_BlockInfo *bi)
 {
 
@@ -2762,7 +2546,7 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
        if (!bi->hasShrinkHeader)
                return 1;       /* can gc */
 
-       yaffs_FindOldestDirtySequence(dev);
+       yaffs2_FindOldestDirtySequence(dev);
 
        /* Can't do gc of this block if there are any blocks older than this one that have
         * discarded pages.
@@ -2771,11 +2555,11 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev,
 }
 
 /*
- * yaffs_FindRefreshBlock()
+ * yaffs2_FindRefreshBlock()
  * periodically finds the oldest full block by sequence number for refreshing.
  * Only for yaffs2.
  */
-static __u32 yaffs_FindRefreshBlock(yaffs_Device *dev)
+static __u32 yaffs2_FindRefreshBlock(yaffs_Device *dev)
 {
        __u32 b ;
 
@@ -2784,11 +2568,13 @@ static __u32 yaffs_FindRefreshBlock(yaffs_Device *dev)
 
        yaffs_BlockInfo *bi;
 
+       if(!dev->param.isYaffs2)
+               return oldest;
+
        /*
         * If refresh period < 10 then refreshing is disabled.
         */
-       if(dev->param.refreshPeriod < 10 ||
-               !dev->param.isYaffs2)
+       if(dev->param.refreshPeriod < 10)
                return oldest;
 
         /*
@@ -2845,7 +2631,7 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo)
                (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
                blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
 
-       yaffs_ClearOldestDirtySequence(dev,bi);
+       yaffs2_ClearOldestDirtySequence(dev,bi);
 
        bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
 
@@ -2860,7 +2646,7 @@ static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo)
        }
 
        if (!bi->needsRetiring) {
-               yaffs_InvalidateCheckpoint(dev);
+               yaffs2_InvalidateCheckpoint(dev);
                erasedOk = yaffs_EraseBlockInNAND(dev, blockNo);
                if (!erasedOk) {
                        dev->nErasureFailures++;
@@ -2956,22 +2742,39 @@ static int yaffs_FindBlockForAllocation(yaffs_Device *dev)
 
 
 
-static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
+static int yaffs2_CheckpointRequired(yaffs_Device *dev)
 {
+       int nblocks;
+       
+       if(!dev->param.isYaffs2)
+               return 0;
+       
+       nblocks = dev->internalEndBlock - dev->internalStartBlock + 1 ;
+
+       return  !dev->param.skipCheckpointWrite &&
+               (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS);
+}
+
+static int yaffs2_CalcCheckpointBlocksRequired(yaffs_Device *dev)
+{
+       int retval;
+
+       if(!dev->param.isYaffs2)
+               return 0;
+
        if (!dev->nCheckpointBlocksRequired &&
-          dev->param.isYaffs2) {
+               yaffs2_CheckpointRequired(dev)){
                /* Not a valid value so recalculate */
                int nBytes = 0;
                int nBlocks;
                int devBlocks = (dev->param.endBlock - dev->param.startBlock + 1);
-               int tnodeSize = yaffs_CalcTnodeSize(dev);
 
                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_CheckpointObject) + sizeof(__u32)) * (dev->nObjects);
+               nBytes += (dev->tnodeSize + sizeof(__u32)) * (dev->nTnodes);
                nBytes += sizeof(yaffs_CheckpointValidity);
                nBytes += sizeof(__u32); /* checksum*/
 
@@ -2982,7 +2785,10 @@ static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
                dev->nCheckpointBlocksRequired = nBlocks;
        }
 
-       return dev->nCheckpointBlocksRequired;
+       retval = dev->nCheckpointBlocksRequired - dev->blocksInCheckpoint;
+       if(retval < 0)
+               retval = 0;
+       return retval;
 }
 
 /*
@@ -2995,14 +2801,7 @@ static int yaffs_CheckSpaceForAllocation(yaffs_Device *dev, int nChunks)
        int reservedBlocks = dev->param.nReservedBlocks;
        int checkpointBlocks;
 
-       if (dev->param.isYaffs2) {
-               checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) -
-                                   dev->blocksInCheckpoint;
-               if (checkpointBlocks < 0)
-                       checkpointBlocks = 0;
-       } else {
-               checkpointBlocks = 0;
-       }
+       checkpointBlocks = yaffs2_CalcCheckpointBlocksRequired(dev);
 
        reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->param.nChunksPerBlock);
 
@@ -3389,7 +3188,7 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,
                        if (bi->gcPrioritise) {
                                prioritisedExists = 1;
                                if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
-                                  yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {
+                                  yaffs2_BlockNotDisqualifiedFromGC(dev, bi)) {
                                        selected = i;
                                        prioritised = 1;
                                }
@@ -3455,7 +3254,7 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,
                        if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
                                pagesUsed < dev->param.nChunksPerBlock &&
                                (dev->gcDirtiest < 1 || pagesUsed < dev->gcPagesInUse) &&
-                               yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {
+                               yaffs2_BlockNotDisqualifiedFromGC(dev, bi)) {
                                dev->gcDirtiest = dev->gcBlockFinder;
                                dev->gcPagesInUse = pagesUsed;
                        }
@@ -3472,7 +3271,7 @@ static unsigned yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,
 
        if(!selected && dev->param.isYaffs2 &&
                dev->gcNotDone >= ( background ? 10 : 20)){
-               yaffs_FindOldestDirtySequence(dev);
+               yaffs2_FindOldestDirtySequence(dev);
                if(dev->oldestDirtyBlock > 0) {
                        selected = dev->oldestDirtyBlock;
                        dev->gcDirtiest = selected;
@@ -3547,9 +3346,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background)
        do {
                maxTries++;
 
-               checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
-               if (checkpointBlockAdjust < 0)
-                       checkpointBlockAdjust = 0;
+               checkpointBlockAdjust = yaffs2_CalcCheckpointBlocksRequired(dev);
 
                minErased  = dev->param.nReservedBlocks + checkpointBlockAdjust + 1;
                erasedChunks = dev->nErasedBlocks * dev->param.nChunksPerBlock;
@@ -3575,7 +3372,7 @@ static int yaffs_CheckGarbageCollection(yaffs_Device *dev, int background)
                 /* If we don't already have a block being gc'd then see if we should start another */
 
                if (dev->gcBlock < 1 && !aggressive) {
-                       dev->gcBlock = yaffs_FindRefreshBlock(dev);
+                       dev->gcBlock = yaffs2_FindRefreshBlock(dev);
                        dev->gcChunk = 0;
                }
                if (dev->gcBlock < 1) {
@@ -3814,7 +3611,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode,
                 */
 
                if (existingChunk > 0) {
-                       /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
+                       /* NB Right now existing chunk will not be real chunkId if the chunk group size > 1
                         *    thus we have to do a FindChunkInFile to get the real chunk id.
                         *
                         * We have a duplicate now we need to decide which one to use:
@@ -3856,8 +3653,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode,
                        }
 
                        if ((inScan > 0) &&
-                           (in->myDev->param.isYaffs2 ||
-                            existingChunk <= 0 ||
+                           (existingChunk <= 0 ||
                             ((existingSerial + 1) & 3) == newSerial)) {
                                /* Forward scanning.
                                 * Use new
@@ -3927,13 +3723,13 @@ void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn)
 
        bi = yaffs_GetBlockInfo(dev, block);
        
-       yaffs_UpdateOldestDirtySequence(dev, block, bi);
+       yaffs2_UpdateOldestDirtySequence(dev, block, bi);
 
        T(YAFFS_TRACE_DELETION,
          (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));
 
-       if (markNAND &&
-           bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->param.isYaffs2) {
+       if (!dev->param.isYaffs2 && markNAND &&
+           bi->blockState != YAFFS_BLOCK_STATE_COLLECTING) {
 
                yaffs_InitialiseTags(&tags);
 
@@ -4033,7 +3829,7 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object *in, int chunkInInode,
  * If name is not NULL, then that new name is used.
  */
 int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force,
-                            int isShrink, int shadows)
+                            int isShrink, int shadows, yaffs_XAttrMod *xmod)
 {
 
        yaffs_BlockInfo *bi;
@@ -4059,7 +3855,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force,
 
        if (!in->fake ||
                in == dev->rootDir || /* The rootDir should also be saved */
-               force) {
+               force  || xmod) {
 
                yaffs_CheckGarbageCollection(dev,0);
                yaffs_CheckObjectDetailsLoaded(in);
@@ -4076,9 +3872,9 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force,
                        yaffs_VerifyObjectHeader(in, oh, &oldTags, 0);
 
                        memcpy(oldName, oh->name, sizeof(oh->name));
-               }
-
-               memset(buffer, 0xFF, dev->nDataBytesPerChunk);
+                       memset(buffer, 0xFF, sizeof(yaffs_ObjectHeader));
+               } else
+                       memset(buffer, 0xFF, dev->nDataBytesPerChunk);
 
                oh->type = in->variantType;
                oh->yst_mode = in->yst_mode;
@@ -4146,6 +3942,11 @@ int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force,
                        break;
                }
 
+               /* process any xattrib modifications */
+               if(xmod)
+                       yaffs_ApplyXMod(dev, (char *)buffer, xmod);
+
+
                /* Tags */
                yaffs_InitialiseTags(&newTags);
                in->serial++;
@@ -4460,7 +4261,7 @@ static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)
 /*--------------------- Checkpointing --------------------*/
 
 
-static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev, int head)
+static int yaffs2_WriteCheckpointValidityMarker(yaffs_Device *dev, int head)
 {
        yaffs_CheckpointValidity cp;
 
@@ -4471,16 +4272,16 @@ static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev, int head)
        cp.version = YAFFS_CHECKPOINT_VERSION;
        cp.head = (head) ? 1 : 0;
 
-       return (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)) ?
+       return (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)) ?
                1 : 0;
 }
 
-static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
+static int yaffs2_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
 {
        yaffs_CheckpointValidity cp;
        int ok;
 
-       ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp));
+       ok = (yaffs2_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp));
 
        if (ok)
                ok = (cp.structType == sizeof(cp)) &&
@@ -4490,7 +4291,7 @@ static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
        return ok ? 1 : 0;
 }
 
-static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
+static void yaffs2_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
                                           yaffs_Device *dev)
 {
        cp->nErasedBlocks = dev->nErasedBlocks;
@@ -4505,7 +4306,7 @@ static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
 
 }
 
-static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
+static void yaffs2_CheckpointDeviceToDevice(yaffs_Device *dev,
                                           yaffs_CheckpointDevice *cp)
 {
        dev->nErasedBlocks = cp->nErasedBlocks;
@@ -4520,7 +4321,7 @@ static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
 }
 
 
-static int yaffs_WriteCheckpointDevice(yaffs_Device *dev)
+static int yaffs2_WriteCheckpointDevice(yaffs_Device *dev)
 {
        yaffs_CheckpointDevice cp;
        __u32 nBytes;
@@ -4529,27 +4330,27 @@ static int yaffs_WriteCheckpointDevice(yaffs_Device *dev)
        int ok;
 
        /* Write device runtime values*/
-       yaffs_DeviceToCheckpointDevice(&cp, dev);
+       yaffs2_DeviceToCheckpointDevice(&cp, dev);
        cp.structType = sizeof(cp);
 
-       ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));
+       ok = (yaffs2_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);
+               ok = (yaffs2_CheckpointWrite(dev, dev->blockInfo, nBytes) == nBytes);
        }
 
        /* Write chunk bits */
        if (ok) {
                nBytes = nBlocks * dev->chunkBitmapStride;
-               ok = (yaffs_CheckpointWrite(dev, dev->chunkBits, nBytes) == nBytes);
+               ok = (yaffs2_CheckpointWrite(dev, dev->chunkBits, nBytes) == nBytes);
        }
        return   ok ? 1 : 0;
 
 }
 
-static int yaffs_ReadCheckpointDevice(yaffs_Device *dev)
+static int yaffs2_ReadCheckpointDevice(yaffs_Device *dev)
 {
        yaffs_CheckpointDevice cp;
        __u32 nBytes;
@@ -4557,7 +4358,7 @@ static int yaffs_ReadCheckpointDevice(yaffs_Device *dev)
 
        int ok;
 
-       ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp));
+       ok = (yaffs2_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp));
        if (!ok)
                return 0;
 
@@ -4565,22 +4366,22 @@ static int yaffs_ReadCheckpointDevice(yaffs_Device *dev)
                return 0;
 
 
-       yaffs_CheckpointDeviceToDevice(dev, &cp);
+       yaffs2_CheckpointDeviceToDevice(dev, &cp);
 
        nBytes = nBlocks * sizeof(yaffs_BlockInfo);
 
-       ok = (yaffs_CheckpointRead(dev, dev->blockInfo, nBytes) == nBytes);
+       ok = (yaffs2_CheckpointRead(dev, dev->blockInfo, nBytes) == nBytes);
 
        if (!ok)
                return 0;
        nBytes = nBlocks * dev->chunkBitmapStride;
 
-       ok = (yaffs_CheckpointRead(dev, dev->chunkBits, nBytes) == nBytes);
+       ok = (yaffs2_CheckpointRead(dev, dev->chunkBits, nBytes) == nBytes);
 
        return ok ? 1 : 0;
 }
 
-static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
+static void yaffs2_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
                                           yaffs_Object *obj)
 {
 
@@ -4603,7 +4404,7 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
                cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId;
 }
 
-static int yaffs_CheckpointObjectToObject(yaffs_Object *obj, yaffs_CheckpointObject *cp)
+static int yaffs2_CheckpointObjectToObject(yaffs_Object *obj, yaffs_CheckpointObject *cp)
 {
 
        yaffs_Object *parent;
@@ -4667,7 +4468,6 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn,
        int i;
        yaffs_Device *dev = in->myDev;
        int ok = 1;
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
 
        if (tn) {
                if (level > 0) {
@@ -4682,9 +4482,9 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn,
                        }
                } else if (level == 0) {
                        __u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
-                       ok = (yaffs_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset));
+                       ok = (yaffs2_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset));
                        if (ok)
-                               ok = (yaffs_CheckpointWrite(dev, tn, tnodeSize) == tnodeSize);
+                               ok = (yaffs2_CheckpointWrite(dev, tn, dev->tnodeSize) == dev->tnodeSize);
                }
        }
 
@@ -4692,7 +4492,7 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn,
 
 }
 
-static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj)
+static int yaffs2_WriteCheckpointTnodes(yaffs_Object *obj)
 {
        __u32 endMarker = ~0;
        int ok = 1;
@@ -4703,14 +4503,14 @@ static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj)
                                            obj->variant.fileVariant.topLevel,
                                            0);
                if (ok)
-                       ok = (yaffs_CheckpointWrite(obj->myDev, &endMarker, sizeof(endMarker)) ==
+                       ok = (yaffs2_CheckpointWrite(obj->myDev, &endMarker, sizeof(endMarker)) ==
                                sizeof(endMarker));
        }
 
        return ok ? 1 : 0;
 }
 
-static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
+static int yaffs2_ReadCheckpointTnodes(yaffs_Object *obj)
 {
        __u32 baseChunk;
        int ok = 1;
@@ -4718,19 +4518,18 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
        yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
        yaffs_Tnode *tn;
        int nread = 0;
-       int tnodeSize = yaffs_CalcTnodeSize(dev);
 
-       ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
+       ok = (yaffs2_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
 
        while (ok && (~baseChunk)) {
                nread++;
                /* Read level 0 tnode */
 
 
-               tn = yaffs_GetTnodeRaw(dev);
-               if (tn)
-                       ok = (yaffs_CheckpointRead(dev, tn, tnodeSize) == tnodeSize);
-               else
+               tn = yaffs_GetTnode(dev);
+               if (tn){
+                       ok = (yaffs2_CheckpointRead(dev, tn, dev->tnodeSize) == dev->tnodeSize);
+               else
                        ok = 0;
 
                if (tn && ok)
@@ -4740,7 +4539,7 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
                                                        tn) ? 1 : 0;
 
                if (ok)
-                       ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
+                       ok = (yaffs2_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));
 
        }
 
@@ -4752,7 +4551,7 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
 }
 
 
-static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
+static int yaffs2_WriteCheckpointObjects(yaffs_Device *dev)
 {
        yaffs_Object *obj;
        yaffs_CheckpointObject cp;
@@ -4770,17 +4569,17 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
                        if (lh) {
                                obj = ylist_entry(lh, yaffs_Object, hashLink);
                                if (!obj->deferedFree) {
-                                       yaffs_ObjectToCheckpointObject(&cp, obj);
+                                       yaffs2_ObjectToCheckpointObject(&cp, obj);
                                        cp.structType = sizeof(cp);
 
                                        T(YAFFS_TRACE_CHECKPOINT, (
                                                TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %p" TENDSTR),
                                                cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk, obj));
 
-                                       ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));
+                                       ok = (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));
 
                                        if (ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE)
-                                               ok = yaffs_WriteCheckpointTnodes(obj);
+                                               ok = yaffs2_WriteCheckpointTnodes(obj);
                                }
                        }
                }
@@ -4791,12 +4590,12 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
        cp.structType = sizeof(cp);
 
        if (ok)
-               ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));
+               ok = (yaffs2_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));
 
        return ok ? 1 : 0;
 }
 
-static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
+static int yaffs2_ReadCheckpointObjects(yaffs_Device *dev)
 {
        yaffs_Object *obj;
        yaffs_CheckpointObject cp;
@@ -4805,7 +4604,7 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
        yaffs_Object *hardList = NULL;
 
        while (ok && !done) {
-               ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp));
+               ok = (yaffs2_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp));
                if (cp.structType != sizeof(cp)) {
                        T(YAFFS_TRACE_CHECKPOINT, (TSTR("struct size %d instead of %d ok %d"TENDSTR),
                                cp.structType, (int)sizeof(cp), ok));
@@ -4820,11 +4619,11 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
                else if (ok) {
                        obj = yaffs_FindOrCreateObjectByNumber(dev, cp.objectId, cp.variantType);
                        if (obj) {
-                               ok = yaffs_CheckpointObjectToObject(obj, &cp);
+                               ok = yaffs2_CheckpointObjectToObject(obj, &cp);
                                if (!ok)
                                        break;
                                if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
-                                       ok = yaffs_ReadCheckpointTnodes(obj);
+                                       ok = yaffs2_ReadCheckpointTnodes(obj);
                                } else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
                                        obj->hardLinks.next =
                                                (struct ylist_head *) hardList;
@@ -4841,14 +4640,14 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
        return ok ? 1 : 0;
 }
 
-static int yaffs_WriteCheckpointSum(yaffs_Device *dev)
+static int yaffs2_WriteCheckpointSum(yaffs_Device *dev)
 {
        __u32 checkpointSum;
        int ok;
 
-       yaffs_GetCheckpointSum(dev, &checkpointSum);
+       yaffs2_GetCheckpointSum(dev, &checkpointSum);
 
-       ok = (yaffs_CheckpointWrite(dev, &checkpointSum, sizeof(checkpointSum)) == sizeof(checkpointSum));
+       ok = (yaffs2_CheckpointWrite(dev, &checkpointSum, sizeof(checkpointSum)) == sizeof(checkpointSum));
 
        if (!ok)
                return 0;
@@ -4856,15 +4655,15 @@ static int yaffs_WriteCheckpointSum(yaffs_Device *dev)
        return 1;
 }
 
-static int yaffs_ReadCheckpointSum(yaffs_Device *dev)
+static int yaffs2_ReadCheckpointSum(yaffs_Device *dev)
 {
        __u32 checkpointSum0;
        __u32 checkpointSum1;
        int ok;
 
-       yaffs_GetCheckpointSum(dev, &checkpointSum0);
+       yaffs2_GetCheckpointSum(dev, &checkpointSum0);
 
-       ok = (yaffs_CheckpointRead(dev, &checkpointSum1, sizeof(checkpointSum1)) == sizeof(checkpointSum1));
+       ok = (yaffs2_CheckpointRead(dev, &checkpointSum1, sizeof(checkpointSum1)) == sizeof(checkpointSum1));
 
        if (!ok)
                return 0;
@@ -4876,39 +4675,39 @@ static int yaffs_ReadCheckpointSum(yaffs_Device *dev)
 }
 
 
-static int yaffs_WriteCheckpointData(yaffs_Device *dev)
+static int yaffs2_WriteCheckpointData(yaffs_Device *dev)
 {
        int ok = 1;
 
-       if (dev->param.skipCheckpointWrite || !dev->param.isYaffs2) {
+       if (!yaffs2_CheckpointRequired(dev)) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint write" TENDSTR)));
                ok = 0;
        }
 
        if (ok)
-               ok = yaffs_CheckpointOpen(dev, 1);
+               ok = yaffs2_CheckpointOpen(dev, 1);
 
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR)));
-               ok = yaffs_WriteCheckpointValidityMarker(dev, 1);
+               ok = yaffs2_WriteCheckpointValidityMarker(dev, 1);
        }
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint device" TENDSTR)));
-               ok = yaffs_WriteCheckpointDevice(dev);
+               ok = yaffs2_WriteCheckpointDevice(dev);
        }
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint objects" TENDSTR)));
-               ok = yaffs_WriteCheckpointObjects(dev);
+               ok = yaffs2_WriteCheckpointObjects(dev);
        }
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR)));
-               ok = yaffs_WriteCheckpointValidityMarker(dev, 0);
+               ok = yaffs2_WriteCheckpointValidityMarker(dev, 0);
        }
 
        if (ok)
-               ok = yaffs_WriteCheckpointSum(dev);
+               ok = yaffs2_WriteCheckpointSum(dev);
 
-       if (!yaffs_CheckpointClose(dev))
+       if (!yaffs2_CheckpointClose(dev))
                ok = 0;
 
        if (ok)
@@ -4919,41 +4718,44 @@ static int yaffs_WriteCheckpointData(yaffs_Device *dev)
        return dev->isCheckpointed;
 }
 
-static int yaffs_ReadCheckpointData(yaffs_Device *dev)
+static int yaffs2_ReadCheckpointData(yaffs_Device *dev)
 {
        int ok = 1;
+       
+       if(!dev->param.isYaffs2)
+               ok = 0;
 
-       if (dev->param.skipCheckpointRead || !dev->param.isYaffs2) {
+       if (ok && dev->param.skipCheckpointRead) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint read" TENDSTR)));
                ok = 0;
        }
 
        if (ok)
-               ok = yaffs_CheckpointOpen(dev, 0); /* open for read */
+               ok = yaffs2_CheckpointOpen(dev, 0); /* open for read */
 
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR)));
-               ok = yaffs_ReadCheckpointValidityMarker(dev, 1);
+               ok = yaffs2_ReadCheckpointValidityMarker(dev, 1);
        }
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint device" TENDSTR)));
-               ok = yaffs_ReadCheckpointDevice(dev);
+               ok = yaffs2_ReadCheckpointDevice(dev);
        }
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint objects" TENDSTR)));
-               ok = yaffs_ReadCheckpointObjects(dev);
+               ok = yaffs2_ReadCheckpointObjects(dev);
        }
        if (ok) {
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR)));
-               ok = yaffs_ReadCheckpointValidityMarker(dev, 0);
+               ok = yaffs2_ReadCheckpointValidityMarker(dev, 0);
        }
 
        if (ok) {
-               ok = yaffs_ReadCheckpointSum(dev);
+               ok = yaffs2_ReadCheckpointSum(dev);
                T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint checksum %d" TENDSTR), ok));
        }
 
-       if (!yaffs_CheckpointClose(dev))
+       if (!yaffs2_CheckpointClose(dev))
                ok = 0;
 
        if (ok)
@@ -4965,12 +4767,12 @@ static int yaffs_ReadCheckpointData(yaffs_Device *dev)
 
 }
 
-static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
+static void yaffs2_InvalidateCheckpoint(yaffs_Device *dev)
 {
        if (dev->isCheckpointed ||
                        dev->blocksInCheckpoint > 0) {
                dev->isCheckpointed = 0;
-               yaffs_CheckpointInvalidateStream(dev);
+               yaffs2_CheckpointInvalidateStream(dev);
        }
        if (dev->param.markSuperBlockDirty)
                dev->param.markSuperBlockDirty(dev);
@@ -4987,8 +4789,8 @@ int yaffs_CheckpointSave(yaffs_Device *dev)
        yaffs_VerifyFreeChunks(dev);
 
        if (!dev->isCheckpointed) {
-               yaffs_InvalidateCheckpoint(dev);
-               yaffs_WriteCheckpointData(dev);
+               yaffs2_InvalidateCheckpoint(dev);
+               yaffs2_WriteCheckpointData(dev);
        }
 
        T(YAFFS_TRACE_ALWAYS, (TSTR("save exit: isCheckpointed %d"TENDSTR), dev->isCheckpointed));
@@ -4996,12 +4798,12 @@ int yaffs_CheckpointSave(yaffs_Device *dev)
        return dev->isCheckpointed;
 }
 
-int yaffs_CheckpointRestore(yaffs_Device *dev)
+int yaffs2_CheckpointRestore(yaffs_Device *dev)
 {
        int retval;
        T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore entry: isCheckpointed %d"TENDSTR), dev->isCheckpointed));
 
-       retval = yaffs_ReadCheckpointData(dev);
+       retval = yaffs2_ReadCheckpointData(dev);
 
        if (dev->isCheckpointed) {
                yaffs_VerifyObjects(dev);
@@ -5136,8 +4938,6 @@ int yaffs_DoWriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset,
        dev = in->myDev;
 
        while (n > 0 && chunkWritten >= 0) {
-               /* chunk = offset / dev->nDataBytesPerChunk + 1; */
-               /* start = offset % dev->nDataBytesPerChunk; */
                yaffs_AddrToChunk(dev, offset, &chunk, &start);
 
                if (chunk * dev->nDataBytesPerChunk + start != offset ||
@@ -5147,7 +4947,7 @@ int yaffs_DoWriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset,
                           TENDSTR),
                           (int)offset, chunk, start));
                }
-               chunk++;
+               chunk++; /* File pos to chunk in file offset */
 
                /* OK now check for the curveball where the start and end are in
                 * the same chunk.
@@ -5297,7 +5097,7 @@ int yaffs_DoWriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset,
 int yaffs_WriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset,
                        int nBytes, int writeThrough)
 {
-       yaffs_HandleHole(in,offset);
+       yaffs2_HandleHole(in,offset);
        return yaffs_DoWriteDataToFile(in,buffer,offset,nBytes,writeThrough);
 }
 
@@ -5378,7 +5178,7 @@ static void yaffs_ResizeDown( yaffs_Object *obj, loff_t newSize)
 }
 
 
-static int yaffs_HandleHole(yaffs_Object *obj, loff_t newSize)
+static int yaffs2_HandleHole(yaffs_Object *obj, loff_t newSize)
 {
        /* if newsSize > oldFileSize.
         * We're going to be writing a hole.
@@ -5456,7 +5256,7 @@ static int yaffs_HandleHole(yaffs_Object *obj, loff_t newSize)
                obj->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
                obj->parent->objectId != YAFFS_OBJECTID_DELETED){
                /* Write a hole start header with the old file size */
-               yaffs_UpdateObjectHeader(obj, NULL, 0,1,0);
+               yaffs_UpdateObjectHeader(obj, NULL, 0, 1, 0, NULL);
        }
 
        return result;
@@ -5480,7 +5280,7 @@ int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize)
                return YAFFS_OK;
                
        if(newSize > oldFileSize){
-               yaffs_HandleHole(in,newSize);
+               yaffs2_HandleHole(in,newSize);
                in->variant.fileVariant.fileSize = newSize;
        } else {
                /* newSize < oldFileSize */ 
@@ -5496,7 +5296,7 @@ int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize)
            !in->isShadowed &&
            in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
            in->parent->objectId != YAFFS_OBJECTID_DELETED)
-               yaffs_UpdateObjectHeader(in, NULL, 0,0,0);
+               yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0, NULL);
 
 
        return YAFFS_OK;
@@ -5540,7 +5340,7 @@ int yaffs_FlushFile(yaffs_Object *in, int updateTime, int dataSync)
 #endif
                        }
 
-                       retVal = (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >=
+                       retVal = (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0, NULL) >=
                                0) ? YAFFS_OK : YAFFS_FAIL;
                }
        } else {
@@ -5611,7 +5411,7 @@ static int yaffs_UnlinkFileIfNeeded(yaffs_Object *in)
 int yaffs_DeleteFile(yaffs_Object *in)
 {
        int retVal = YAFFS_OK;
-       int deleted = in->deleted;
+       int deleted; /* Need to cache value on stack if in is freed */
        yaffs_Device *dev = in->myDev;
 
        if (dev->param.disableSoftDelete || dev->param.isYaffs2)
@@ -5624,6 +5424,8 @@ int yaffs_DeleteFile(yaffs_Object *in)
                if (!in->unlinked)
                        retVal = yaffs_UnlinkFileIfNeeded(in);
 
+               deleted = in->deleted;
+
                if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
                        in->deleted = 1;
                        deleted = 1;
@@ -5873,7 +5675,7 @@ static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)
 
 
 
-static int ybicmp(const void *a, const void *b)
+static int yaffs2_ybicmp(const void *a, const void *b)
 {
        register int aseq = ((yaffs_BlockIndex *)a)->seq;
        register int bseq = ((yaffs_BlockIndex *)b)->seq;
@@ -6040,7 +5842,7 @@ static void yaffs_EmptyLostAndFound(yaffs_Device *dev)
        yaffs_DeleteDirectoryContents(dev->lostNFoundDir);
 }
 
-static int yaffs_Scan(yaffs_Device *dev)
+static int yaffs1_Scan(yaffs_Device *dev)
 {
        yaffs_ExtendedTags tags;
        int blk;
@@ -6070,7 +5872,7 @@ static int yaffs_Scan(yaffs_Device *dev)
 
 
        T(YAFFS_TRACE_SCAN,
-         (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
+         (TSTR("yaffs1_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
           dev->internalStartBlock, dev->internalEndBlock));
 
        chunkData = yaffs_GetTempBuffer(dev, __LINE__);
@@ -6463,7 +6265,7 @@ static int yaffs_Scan(yaffs_Device *dev)
                        obj = yaffs_FindObjectByNumber(dev, fixer->objectId);
 
                        if (obj)
-                               yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0);
+                               yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL);
 
                        YFREE(fixer);
                }
@@ -6474,7 +6276,7 @@ static int yaffs_Scan(yaffs_Device *dev)
        if (alloc_failed)
                return YAFFS_FAIL;
 
-       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
+       T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_Scan ends" TENDSTR)));
 
 
        return YAFFS_OK;
@@ -6537,7 +6339,7 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
        }
 }
 
-static int yaffs_ScanBackwards(yaffs_Device *dev)
+static int yaffs2_ScanBackwards(yaffs_Device *dev)
 {
        yaffs_ExtendedTags tags;
        int blk;
@@ -6571,15 +6373,9 @@ static int yaffs_ScanBackwards(yaffs_Device *dev)
        yaffs_BlockIndex *blockIndex = NULL;
        int altBlockIndex = 0;
 
-       if (!dev->param.isYaffs2) {
-               T(YAFFS_TRACE_SCAN,
-                 (TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR)));
-               return YAFFS_FAIL;
-       }
-
        T(YAFFS_TRACE_SCAN,
          (TSTR
-          ("yaffs_ScanBackwards starts  intstartblk %d intendblk %d..."
+          ("yaffs2_ScanBackwards starts  intstartblk %d intendblk %d..."
            TENDSTR), dev->internalStartBlock, dev->internalEndBlock));
 
 
@@ -6594,7 +6390,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev)
 
        if (!blockIndex) {
                T(YAFFS_TRACE_SCAN,
-                 (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
+                 (TSTR("yaffs2_ScanBackwards() could not allocate block index!" TENDSTR)));
                return YAFFS_FAIL;
        }
 
@@ -6667,29 +6463,8 @@ static int yaffs_ScanBackwards(yaffs_Device *dev)
 
        YYIELD();
 
-       /* Sort the blocks */
-#ifndef CONFIG_YAFFS_USE_OWN_SORT
-       {
-               /* Use qsort now. */
-               yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
-       }
-#else
-       {
-               /* Dungy old bubble sort... */
-
-               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;
-                               }
-       }
-#endif
+       /* Sort the blocks by sequence number*/
+       yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), yaffs2_ybicmp);
 
        YYIELD();
 
@@ -6771,7 +6546,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev)
                                                         * the current allocation block.
                                                         */
 
-                                                        T(YAFFS_TRACE_ALWAYS,
+                                                        T(YAFFS_TRACE_SCAN,
                                                         (TSTR("Partially written block %d detected" TENDSTR),
                                                         blk));
                                                }
@@ -7180,7 +6955,7 @@ static int yaffs_ScanBackwards(yaffs_Device *dev)
        if (alloc_failed)
                return YAFFS_FAIL;
 
-       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
+       T(YAFFS_TRACE_SCAN, (TSTR("yaffs2_ScanBackwards ends" TENDSTR)));
 
        return YAFFS_OK;
 }
@@ -7297,7 +7072,7 @@ static void yaffs_UpdateParent(yaffs_Object *obj)
                }
 
        } else
-               yaffs_UpdateObjectHeader(obj,NULL,0,0,0);
+               yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL);
 }
 
 void yaffs_UpdateDirtyDirectories(yaffs_Device *dev)
@@ -7320,7 +7095,7 @@ void yaffs_UpdateDirtyDirectories(yaffs_Device *dev)
                T(YAFFS_TRACE_BACKGROUND, (TSTR("Update directory %d" TENDSTR), obj->objectId));
 
                if(obj->dirty)
-                       yaffs_UpdateObjectHeader(obj,NULL,0,0,0);
+                       yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, NULL);
        }
 }
 
@@ -7651,7 +7426,7 @@ int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr)
        if (valid & ATTR_SIZE)
                yaffs_ResizeFile(obj, attr->ia_size);
 
-       yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0);
+       yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0, NULL);
 
        return YAFFS_OK;
 
@@ -7684,6 +7459,104 @@ int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr)
 
 #endif
 
+
+static int yaffs_DoXMod(yaffs_Object *obj, int set, const char *name, const void *value, int size, int flags)
+{
+       yaffs_XAttrMod xmod;
+
+       int result;
+
+       xmod.set = set;
+       xmod.name = name;
+       xmod.data = value;
+       xmod.size =  size;
+       xmod.flags = flags;
+       xmod.result = -ENOSPC;
+
+       result = yaffs_UpdateObjectHeader(obj, NULL, 0, 0, 0, &xmod);
+
+       if(result > 0)
+               return xmod.result;
+       else
+               return -ENOSPC;
+}
+
+static int yaffs_ApplyXMod(yaffs_Device *dev, char *buffer, yaffs_XAttrMod *xmod)
+{
+       int retval = 0;
+       int x_offs = sizeof(yaffs_ObjectHeader);
+       int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader);
+
+       char * x_buffer = buffer + x_offs;
+
+       if(xmod->set)
+               retval = nval_set(x_buffer, x_size, xmod->name, xmod->data, xmod->size, xmod->flags);
+       else
+               retval = nval_del(x_buffer, x_size, xmod->name);
+
+       xmod->result = retval;
+
+       return retval;
+}
+
+static int yaffs_DoXFetch(yaffs_Object *obj, const char *name, void *value, int size)
+{
+       char *buffer = NULL;
+       int result;
+       yaffs_ExtendedTags tags;
+       yaffs_Device *dev = obj->myDev;
+       int x_offs = sizeof(yaffs_ObjectHeader);
+       int x_size = dev->nDataBytesPerChunk - sizeof(yaffs_ObjectHeader);
+
+       __u8 * x_buffer;
+
+       int retval = 0;
+
+       if(obj->hdrChunk < 1)
+               return -ENODATA;
+
+       buffer = yaffs_GetTempBuffer(dev, __LINE__);
+       if(!buffer)
+               return -ENOMEM;
+
+       result = yaffs_ReadChunkWithTagsFromNAND(dev,obj->hdrChunk, buffer, &tags);
+
+       if(result != YAFFS_OK)
+               retval = -ENOENT;
+       else{
+               x_buffer =  buffer + x_offs;
+
+               if(name)
+                       retval = nval_get(x_buffer, x_size, name, value, size);
+               else
+                       retval = nval_list(x_buffer, x_size, value,size);
+       }
+       yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
+       return retval;
+}
+
+int yaffs_SetXAttribute(yaffs_Object *obj, const char *name, const void * value, int size, int flags)
+{
+       return yaffs_DoXMod(obj, 1, name, value, size, flags);
+}
+
+int yaffs_RemoveXAttribute(yaffs_Object *obj, const char *name)
+{
+       return yaffs_DoXMod(obj, 0, name, NULL, 0, 0);
+}
+
+int yaffs_GetXAttribute(yaffs_Object *obj, const char *name, void *value, int size)
+{
+       return yaffs_DoXFetch(obj, name, value, size);
+}
+
+int yaffs_ListXAttributes(yaffs_Object *obj, char *buffer, int size)
+{
+       return yaffs_DoXFetch(obj, NULL, buffer,size);
+}
+
+
+
 #if 0
 int yaffs_DumpObject(yaffs_Object *obj)
 {
@@ -7899,6 +7772,9 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        else
                dev->chunkGroupBits = bits - dev->tnodeWidth;
 
+       dev->tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
+       if(dev->tnodeSize < sizeof(yaffs_Tnode))
+               dev->tnodeSize = sizeof(yaffs_Tnode);
 
        dev->chunkGroupSize = 1 << dev->chunkGroupBits;
 
@@ -7988,8 +7864,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        if (!init_failed && !yaffs_InitialiseBlocks(dev))
                init_failed = 1;
 
-       yaffs_InitialiseTnodes(dev);
-       yaffs_InitialiseObjects(dev);
+       yaffs_InitialiseTnodesAndObjects(dev);
 
        if (!init_failed && !yaffs_CreateInitialDirectories(dev))
                init_failed = 1;
@@ -7998,7 +7873,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
        if (!init_failed) {
                /* Now scan the flash. */
                if (dev->param.isYaffs2) {
-                       if (yaffs_CheckpointRestore(dev)) {
+                       if (yaffs2_CheckpointRestore(dev)) {
                                yaffs_CheckObjectDetailsLoaded(dev->rootDir);
                                T(YAFFS_TRACE_ALWAYS,
                                  (TSTR("yaffs: restored from checkpoint" TENDSTR)));
@@ -8008,9 +7883,8 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
                                 * and scan backwards.
                                 */
                                yaffs_DeinitialiseBlocks(dev);
-                               yaffs_DeinitialiseTnodes(dev);
-                               yaffs_DeinitialiseObjects(dev);
 
+                               yaffs_DeinitialiseTnodesAndObjects(dev);
 
                                dev->nErasedBlocks = 0;
                                dev->nFreeChunks = 0;
@@ -8023,16 +7897,15 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
                                if (!init_failed && !yaffs_InitialiseBlocks(dev))
                                        init_failed = 1;
 
-                               yaffs_InitialiseTnodes(dev);
-                               yaffs_InitialiseObjects(dev);
+                               yaffs_InitialiseTnodesAndObjects(dev);
 
                                if (!init_failed && !yaffs_CreateInitialDirectories(dev))
                                        init_failed = 1;
 
-                               if (!init_failed && !yaffs_ScanBackwards(dev))
+                               if (!init_failed && !yaffs2_ScanBackwards(dev))
                                        init_failed = 1;
                        }
-               } else if (!yaffs_Scan(dev))
+               } else if (!yaffs1_Scan(dev))
                                init_failed = 1;
 
                yaffs_StripDeletedObjects(dev);
@@ -8064,7 +7937,7 @@ int yaffs_GutsInitialise(yaffs_Device *dev)
 
        /* Clean up any aborted checkpoint data */
        if(!dev->isCheckpointed && dev->blocksInCheckpoint > 0)
-               yaffs_InvalidateCheckpoint(dev);
+               yaffs2_InvalidateCheckpoint(dev);
 
        T(YAFFS_TRACE_TRACING,
          (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
@@ -8078,8 +7951,7 @@ void yaffs_Deinitialise(yaffs_Device *dev)
                int i;
 
                yaffs_DeinitialiseBlocks(dev);
-               yaffs_DeinitialiseTnodes(dev);
-               yaffs_DeinitialiseObjects(dev);
+               yaffs_DeinitialiseTnodesAndObjects(dev);
                if (dev->param.nShortOpCaches > 0 &&
                    dev->srCache) {
 
@@ -8161,9 +8033,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
        nFree -= ((dev->param.nReservedBlocks + 1) * dev->param.nChunksPerBlock);
 
        /* Now we figure out how much to reserve for the checkpoint and report that... */
-       blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
-       if (blocksForCheckpoint < 0)
-               blocksForCheckpoint = 0;
+       blocksForCheckpoint = yaffs2_CalcCheckpointBlocksRequired(dev);
 
        nFree -= (blocksForCheckpoint * dev->param.nChunksPerBlock);