diff options
Diffstat (limited to 'target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-01-23.patch')
-rw-r--r-- | target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-01-23.patch | 7800 |
1 files changed, 0 insertions, 7800 deletions
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 deleted file mode 100644 index 9bb0826f..0000000 --- a/target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-01-23.patch +++ /dev/null @@ -1,7800 +0,0 @@ ---- 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_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); |