diff -Nur linux-2.6.32.orig/fs/Kconfig linux-2.6.32/fs/Kconfig
--- linux-2.6.32.orig/fs/Kconfig	2009-12-03 04:51:21.000000000 +0100
+++ linux-2.6.32/fs/Kconfig	2010-01-30 20:35:00.921899692 +0100
@@ -174,6 +174,10 @@
 source "fs/befs/Kconfig"
 source "fs/bfs/Kconfig"
 source "fs/efs/Kconfig"
+
+# Patched by YAFFS
+source "fs/yaffs2/Kconfig"
+
 source "fs/jffs2/Kconfig"
 # UBIFS File system configuration
 source "fs/ubifs/Kconfig"
diff -Nur linux-2.6.32.orig/fs/Makefile linux-2.6.32/fs/Makefile
--- linux-2.6.32.orig/fs/Makefile	2009-12-03 04:51:21.000000000 +0100
+++ linux-2.6.32/fs/Makefile	2010-01-30 20:35:00.933084814 +0100
@@ -124,3 +124,4 @@
 obj-$(CONFIG_BTRFS_FS)		+= btrfs/
 obj-$(CONFIG_GFS2_FS)           += gfs2/
 obj-$(CONFIG_EXOFS_FS)          += exofs/
+obj-$(CONFIG_YAFFS_FS)		+= yaffs2/
diff -Nur linux-2.6.32.orig/fs/Makefile.pre.yaffs linux-2.6.32/fs/Makefile.pre.yaffs
--- linux-2.6.32.orig/fs/Makefile.pre.yaffs	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/Makefile.pre.yaffs	2010-01-30 20:35:00.983076819 +0100
@@ -0,0 +1,126 @@
+#
+# Makefile for the Linux filesystems.
+#
+# 14 Sep 2000, Christoph Hellwig <hch@infradead.org>
+# Rewritten to use lists instead of if-statements.
+# 
+
+obj-y :=	open.o read_write.o file_table.o super.o \
+		char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
+		ioctl.o readdir.o select.o fifo.o dcache.o inode.o \
+		attr.o bad_inode.o file.o filesystems.o namespace.o \
+		seq_file.o xattr.o libfs.o fs-writeback.o \
+		pnode.o drop_caches.o splice.o sync.o utimes.o \
+		stack.o
+
+ifeq ($(CONFIG_BLOCK),y)
+obj-y +=	buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o
+else
+obj-y +=	no-block.o
+endif
+
+obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o
+obj-y				+= notify/
+obj-$(CONFIG_EPOLL)		+= eventpoll.o
+obj-$(CONFIG_ANON_INODES)	+= anon_inodes.o
+obj-$(CONFIG_SIGNALFD)		+= signalfd.o
+obj-$(CONFIG_TIMERFD)		+= timerfd.o
+obj-$(CONFIG_EVENTFD)		+= eventfd.o
+obj-$(CONFIG_AIO)               += aio.o
+obj-$(CONFIG_FILE_LOCKING)      += locks.o
+obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
+
+nfsd-$(CONFIG_NFSD)		:= nfsctl.o
+obj-y				+= $(nfsd-y) $(nfsd-m)
+
+obj-$(CONFIG_BINFMT_AOUT)	+= binfmt_aout.o
+obj-$(CONFIG_BINFMT_EM86)	+= binfmt_em86.o
+obj-$(CONFIG_BINFMT_MISC)	+= binfmt_misc.o
+
+# binfmt_script is always there
+obj-y				+= binfmt_script.o
+
+obj-$(CONFIG_BINFMT_ELF)	+= binfmt_elf.o
+obj-$(CONFIG_COMPAT_BINFMT_ELF)	+= compat_binfmt_elf.o
+obj-$(CONFIG_BINFMT_ELF_FDPIC)	+= binfmt_elf_fdpic.o
+obj-$(CONFIG_BINFMT_SOM)	+= binfmt_som.o
+obj-$(CONFIG_BINFMT_FLAT)	+= binfmt_flat.o
+
+obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
+obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
+obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
+obj-$(CONFIG_GENERIC_ACL)	+= generic_acl.o
+
+obj-$(CONFIG_QUOTA)		+= dquot.o
+obj-$(CONFIG_QFMT_V1)		+= quota_v1.o
+obj-$(CONFIG_QFMT_V2)		+= quota_v2.o
+obj-$(CONFIG_QUOTA_TREE)	+= quota_tree.o
+obj-$(CONFIG_QUOTACTL)		+= quota.o
+
+obj-$(CONFIG_PROC_FS)		+= proc/
+obj-y				+= partitions/
+obj-$(CONFIG_SYSFS)		+= sysfs/
+obj-$(CONFIG_CONFIGFS_FS)	+= configfs/
+obj-y				+= devpts/
+
+obj-$(CONFIG_PROFILING)		+= dcookies.o
+obj-$(CONFIG_DLM)		+= dlm/
+ 
+# Do not add any filesystems before this line
+obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
+obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before ext2 so root fs can be ext3
+obj-$(CONFIG_EXT2_FS)		+= ext2/
+# We place ext4 after ext2 so plain ext2 root fs's are mounted using ext2
+# unless explicitly requested by rootfstype
+obj-$(CONFIG_EXT4_FS)		+= ext4/
+obj-$(CONFIG_JBD)		+= jbd/
+obj-$(CONFIG_JBD2)		+= jbd2/
+obj-$(CONFIG_CRAMFS)		+= cramfs/
+obj-$(CONFIG_SQUASHFS)		+= squashfs/
+obj-y				+= ramfs/
+obj-$(CONFIG_HUGETLBFS)		+= hugetlbfs/
+obj-$(CONFIG_CODA_FS)		+= coda/
+obj-$(CONFIG_MINIX_FS)		+= minix/
+obj-$(CONFIG_FAT_FS)		+= fat/
+obj-$(CONFIG_BFS_FS)		+= bfs/
+obj-$(CONFIG_ISO9660_FS)	+= isofs/
+obj-$(CONFIG_HFSPLUS_FS)	+= hfsplus/ # Before hfs to find wrapped HFS+
+obj-$(CONFIG_HFS_FS)		+= hfs/
+obj-$(CONFIG_ECRYPT_FS)		+= ecryptfs/
+obj-$(CONFIG_VXFS_FS)		+= freevxfs/
+obj-$(CONFIG_NFS_FS)		+= nfs/
+obj-$(CONFIG_EXPORTFS)		+= exportfs/
+obj-$(CONFIG_NFSD)		+= nfsd/
+obj-$(CONFIG_LOCKD)		+= lockd/
+obj-$(CONFIG_NLS)		+= nls/
+obj-$(CONFIG_SYSV_FS)		+= sysv/
+obj-$(CONFIG_SMB_FS)		+= smbfs/
+obj-$(CONFIG_CIFS)		+= cifs/
+obj-$(CONFIG_NCP_FS)		+= ncpfs/
+obj-$(CONFIG_HPFS_FS)		+= hpfs/
+obj-$(CONFIG_NTFS_FS)		+= ntfs/
+obj-$(CONFIG_UFS_FS)		+= ufs/
+obj-$(CONFIG_EFS_FS)		+= efs/
+obj-$(CONFIG_JFFS2_FS)		+= jffs2/
+obj-$(CONFIG_UBIFS_FS)		+= ubifs/
+obj-$(CONFIG_AFFS_FS)		+= affs/
+obj-$(CONFIG_ROMFS_FS)		+= romfs/
+obj-$(CONFIG_QNX4FS_FS)		+= qnx4/
+obj-$(CONFIG_AUTOFS_FS)		+= autofs/
+obj-$(CONFIG_AUTOFS4_FS)	+= autofs4/
+obj-$(CONFIG_ADFS_FS)		+= adfs/
+obj-$(CONFIG_FUSE_FS)		+= fuse/
+obj-$(CONFIG_UDF_FS)		+= udf/
+obj-$(CONFIG_SUN_OPENPROMFS)	+= openpromfs/
+obj-$(CONFIG_OMFS_FS)		+= omfs/
+obj-$(CONFIG_JFS_FS)		+= jfs/
+obj-$(CONFIG_XFS_FS)		+= xfs/
+obj-$(CONFIG_9P_FS)		+= 9p/
+obj-$(CONFIG_AFS_FS)		+= afs/
+obj-$(CONFIG_BEFS_FS)		+= befs/
+obj-$(CONFIG_HOSTFS)		+= hostfs/
+obj-$(CONFIG_HPPFS)		+= hppfs/
+obj-$(CONFIG_DEBUG_FS)		+= debugfs/
+obj-$(CONFIG_OCFS2_FS)		+= ocfs2/
+obj-$(CONFIG_BTRFS_FS)		+= btrfs/
+obj-$(CONFIG_GFS2_FS)           += gfs2/
diff -Nur linux-2.6.32.orig/fs/yaffs2/devextras.h linux-2.6.32/fs/yaffs2/devextras.h
--- linux-2.6.32.orig/fs/yaffs2/devextras.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/devextras.h	2010-01-30 20:35:01.021829008 +0100
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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 __KERNEL__)
+
+/* Definition of types */
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned __u32;
+
+#endif
+
+/*
+ * This is a simple doubly linked list implementation that matches the
+ * way the Linux kernel doubly linked list implementation works.
+ */
+
+struct ylist_head {
+	struct ylist_head *next; /* next in chain */
+	struct ylist_head *prev; /* previous in chain */
+};
+
+
+/* Initialise a static list */
+#define YLIST_HEAD(name) \
+struct ylist_head name = { &(name), &(name)}
+
+
+
+/* Initialise a list head to an empty list */
+#define YINIT_LIST_HEAD(p) \
+do { \
+	(p)->next = (p);\
+	(p)->prev = (p); \
+} while (0)
+
+
+/* Add an element to a list */
+static __inline__ void ylist_add(struct ylist_head *newEntry,
+				struct ylist_head *list)
+{
+	struct ylist_head *listNext = list->next;
+
+	list->next = newEntry;
+	newEntry->prev = list;
+	newEntry->next = listNext;
+	listNext->prev = newEntry;
+
+}
+
+static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
+				 struct ylist_head *list)
+{
+	struct ylist_head *listPrev = list->prev;
+
+	list->prev = newEntry;
+	newEntry->next = list;
+	newEntry->prev = listPrev;
+	listPrev->next = newEntry;
+
+}
+
+
+/* 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)
+{
+	struct ylist_head *listNext = entry->next;
+	struct ylist_head *listPrev = entry->prev;
+
+	listNext->prev = listPrev;
+	listPrev->next = listNext;
+
+}
+
+static __inline__ void ylist_del_init(struct ylist_head *entry)
+{
+	ylist_del(entry);
+	entry->next = entry->prev = entry;
+}
+
+
+/* Test if the list is empty */
+static __inline__ int ylist_empty(struct ylist_head *entry)
+{
+	return (entry->next == entry);
+}
+
+
+/* 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.
+ */
+
+
+#define ylist_entry(entry, type, member) \
+	((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
+
+
+/* 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 ylist_for_each(itervar, list) \
+	for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
+
+#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
+
+
+#ifndef WIN32
+#include <sys/stat.h>
+#endif
+
+/*
+ * 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_GID	4
+#define ATTR_SIZE	8
+#define ATTR_ATIME	16
+#define ATTR_MTIME	32
+#define ATTR_CTIME	64
+
+struct iattr {
+	unsigned int ia_valid;
+	unsigned ia_mode;
+	unsigned ia_uid;
+	unsigned ia_gid;
+	unsigned ia_size;
+	unsigned ia_atime;
+	unsigned ia_mtime;
+	unsigned ia_ctime;
+	unsigned int ia_attr_flags;
+};
+
+#endif
+
+#else
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+
+#endif
+
+
+#endif
diff -Nur linux-2.6.32.orig/fs/yaffs2/Kconfig linux-2.6.32/fs/yaffs2/Kconfig
--- linux-2.6.32.orig/fs/yaffs2/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/Kconfig	2010-01-30 20:35:01.053081300 +0100
@@ -0,0 +1,156 @@
+#
+# YAFFS file system configurations
+#
+
+config YAFFS_FS
+	tristate "YAFFS2 file system support"
+	default n
+	depends on MTD_BLOCK
+	select YAFFS_YAFFS1
+	select YAFFS_YAFFS2
+	help
+	  YAFFS2, or Yet Another Flash Filing System, is a filing system
+	  optimised for NAND Flash chips.
+
+	  To compile the YAFFS2 file system support as a module, choose M
+	  here: the module will be called yaffs2.
+
+	  If unsure, say N.
+
+	  Further information on YAFFS2 is available at
+	  <http://www.aleph1.co.uk/yaffs/>.
+
+config YAFFS_YAFFS1
+	bool "512 byte / page devices"
+	depends on YAFFS_FS
+	default y
+	help
+	  Enable YAFFS1 support -- yaffs for 512 byte / page devices
+
+	  Not needed for 2K-page devices.
+
+	  If unsure, say Y.
+
+config YAFFS_9BYTE_TAGS
+	bool "Use older-style on-NAND data format with pageStatus byte"
+	depends on YAFFS_YAFFS1
+	default n
+	help
+
+	  Older-style on-NAND data format has a "pageStatus" byte to record
+	  chunk/page state.  This byte is zero when the page is discarded.
+	  Choose this option if you have existing on-NAND data using this
+	  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
+	  in yaffs_mtdif1.c.
+
+	  If unsure, say N.
+
+config YAFFS_DOES_ECC
+	bool "Lets Yaffs do its own ECC"
+	depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS
+	default n
+	help
+	  This enables Yaffs to use its own ECC functions instead of using
+	  the ones from the generic MTD-NAND driver.
+
+	  If unsure, say N.
+
+config YAFFS_ECC_WRONG_ORDER
+	bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
+	depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS
+	default n
+	help
+	  This makes yaffs_ecc.c use the same ecc byte order as Steven
+	  Hill's nand_ecc.c. If not set, then you get the same ecc byte
+	  order as SmartMedia.
+
+	  If unsure, say N.
+
+config YAFFS_YAFFS2
+	bool "2048 byte (or larger) / page devices"
+	depends on YAFFS_FS
+	default y
+	help
+	  Enable YAFFS2 support -- yaffs for >= 2K bytes per page devices
+
+	  If unsure, say Y.
+
+config YAFFS_AUTO_YAFFS2
+	bool "Autoselect yaffs2 format"
+	depends on YAFFS_YAFFS2
+	default y
+	help
+	  Without this, you need to explicitely use yaffs2 as the file
+	  system type. With this, you can say "yaffs" and yaffs or yaffs2
+	  will be used depending on the device page size (yaffs on
+	  512-byte page devices, yaffs2 on 2K page devices).
+
+	  If unsure, say Y.
+
+config YAFFS_DISABLE_LAZY_LOAD
+	bool "Disable lazy loading"
+	depends on YAFFS_YAFFS2
+	default n
+	help
+	  "Lazy loading" defers loading file details until they are
+	  required. This saves mount time, but makes the first look-up
+	  a bit longer.
+
+	  Lazy loading will only happen if enabled by this option being 'n'
+	  and if the appropriate tags are available, else yaffs2 will
+	  automatically fall back to immediate loading and do the right
+	  thing.
+
+	  Lazy laoding will be required by checkpointing.
+
+	  Setting this to 'y' will disable lazy loading.
+
+	  If unsure, say N.
+
+
+config YAFFS_DISABLE_WIDE_TNODES
+	bool "Turn off wide tnodes"
+	depends on YAFFS_FS
+	default n
+	help
+	  Wide tnodes are only used for NAND arrays >=32MB for 512-byte
+	  page devices and >=128MB for 2k page devices. They use slightly
+	  more RAM but are faster since they eliminate chunk group
+	  searching.
+
+	  Setting this to 'y' will force tnode width to 16 bits and save
+	  memory but make large arrays slower.
+
+	  If unsure, say N.
+
+config YAFFS_ALWAYS_CHECK_CHUNK_ERASED
+	bool "Force chunk erase check"
+	depends on YAFFS_FS
+	default n
+	help
+          Normally YAFFS only checks chunks before writing until an erased
+	  chunk is found. This helps to detect any partially written
+	  chunks that might have happened due to power loss.
+
+	  Enabling this forces on the test that chunks are erased in flash
+	  before writing to them. This takes more time but is potentially
+	  a bit more secure.
+
+	  Suggest setting Y during development and ironing out driver
+	  issues etc. Suggest setting to N if you want faster writing.
+
+	  If unsure, say Y.
+
+config YAFFS_SHORT_NAMES_IN_RAM
+	bool "Cache short names in RAM"
+	depends on YAFFS_FS
+	default y
+	help
+	  If this config is set, then short names are stored with the
+	  yaffs_Object.  This costs an extra 16 bytes of RAM per object,
+	  but makes look-ups faster.
+
+	  If unsure, say Y.
diff -Nur linux-2.6.32.orig/fs/yaffs2/Makefile linux-2.6.32/fs/yaffs2/Makefile
--- linux-2.6.32.orig/fs/yaffs2/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/Makefile	2010-01-30 20:35:01.093074881 +0100
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux YAFFS filesystem routines.
+#
+
+obj-$(CONFIG_YAFFS_FS) += yaffs.o
+
+yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.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_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
diff -Nur linux-2.6.32.orig/fs/yaffs2/moduleconfig.h linux-2.6.32/fs/yaffs2/moduleconfig.h
--- linux-2.6.32.orig/fs/yaffs2/moduleconfig.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/moduleconfig.h	2010-01-30 20:35:01.131828051 +0100
@@ -0,0 +1,65 @@
+/*
+ * 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 Martin Fouts <Martin.Fouts@palmsource.com>
+ *
+ * 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_CONFIG_H__
+#define __YAFFS_CONFIG_H__
+
+#ifdef YAFFS_OUT_OF_TREE
+
+/* DO NOT UNSET THESE THREE. YAFFS2 will not compile if you do. */
+#define CONFIG_YAFFS_FS
+#define CONFIG_YAFFS_YAFFS1
+#define CONFIG_YAFFS_YAFFS2
+
+/* These options are independent of each other.  Select those that matter. */
+
+/* Default: Not selected */
+/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
+/* #define CONFIG_YAFFS_DOES_ECC */
+
+/* Default: Not selected */
+/* Meaning: ECC byte order is 'wrong'.  Only meaningful if */
+/*          CONFIG_YAFFS_DOES_ECC is set */
+/* #define CONFIG_YAFFS_ECC_WRONG_ORDER */
+
+/* Default: Selected */
+/* Meaning: Disables testing whether chunks are erased before writing to them*/
+#define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
+
+/* Default: Selected */
+/* Meaning: Cache short names, taking more RAM, but faster look-ups */
+#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM
+
+/* Default: 10 */
+/* Meaning: set the count of blocks to reserve for checkpointing */
+#define CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS 10
+
+/*
+Older-style on-NAND data format has a "pageStatus" byte to record
+chunk/page state.  This byte is zeroed when the page is discarded.
+Choose this option if you have existing on-NAND data in this 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 in yaffs_mtdif1.c.
+*/
+/* Default: Not selected */
+/* Meaning: Use older-style on-NAND data format with pageStatus byte */
+/* #define CONFIG_YAFFS_9BYTE_TAGS */
+
+#endif /* YAFFS_OUT_OF_TREE */
+
+#endif /* __YAFFS_CONFIG_H__ */
diff -Nur linux-2.6.32.orig/fs/yaffs2/yaffs_checkptrw.c linux-2.6.32/fs/yaffs2/yaffs_checkptrw.c
--- linux-2.6.32.orig/fs/yaffs2/yaffs_checkptrw.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/yaffs_checkptrw.c	2010-01-30 20:35:01.171829690 +0100
@@ -0,0 +1,394 @@
+/*
+ * 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 General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+const char *yaffs_checkptrw_c_version =
+	"$Id: yaffs_checkptrw.c,v 1.18 2009-03-06 17:20:49 wookey Exp $";
+
+
+#include "yaffs_checkptrw.h"
+#include "yaffs_getblockinfo.h"
+
+static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
+{
+	int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
+
+	T(YAFFS_TRACE_CHECKPOINT,
+		(TSTR("checkpt blocks available = %d" TENDSTR),
+		blocksAvailable));
+
+	return (blocksAvailable <= 0) ? 0 : 1;
+}
+
+
+static int yaffs_CheckpointErase(yaffs_Device *dev)
+{
+	int i;
+
+	if (!dev->eraseBlockInNAND)
+		return 0;
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d"TENDSTR),
+		dev->internalStartBlock, dev->internalEndBlock));
+
+	for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
+		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i);
+		if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {
+			T(YAFFS_TRACE_CHECKPOINT, (TSTR("erasing checkpt block %d"TENDSTR), i));
+			if (dev->eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {
+				bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
+				dev->nErasedBlocks++;
+				dev->nFreeChunks += dev->nChunksPerBlock;
+			} else {
+				dev->markNANDBlockBad(dev, i);
+				bi->blockState = YAFFS_BLOCK_STATE_DEAD;
+			}
+		}
+	}
+
+	dev->blocksInCheckpoint = 0;
+
+	return 1;
+}
+
+
+static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)
+{
+	int  i;
+	int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
+	T(YAFFS_TRACE_CHECKPOINT,
+		(TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR),
+		dev->nErasedBlocks, dev->nReservedBlocks, blocksAvailable, dev->checkpointNextBlock));
+
+	if (dev->checkpointNextBlock >= 0 &&
+			dev->checkpointNextBlock <= dev->internalEndBlock &&
+			blocksAvailable > 0) {
+
+		for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {
+			yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i);
+			if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) {
+				dev->checkpointNextBlock = i + 1;
+				dev->checkpointCurrentBlock = i;
+				T(YAFFS_TRACE_CHECKPOINT, (TSTR("allocating checkpt block %d"TENDSTR), i));
+				return;
+			}
+		}
+	}
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("out of checkpt blocks"TENDSTR)));
+
+	dev->checkpointNextBlock = -1;
+	dev->checkpointCurrentBlock = -1;
+}
+
+static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
+{
+	int  i;
+	yaffs_ExtendedTags tags;
+
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: start:  blocks %d next %d" TENDSTR),
+		dev->blocksInCheckpoint, dev->checkpointNextBlock));
+
+	if (dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
+		for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {
+			int chunk = i * dev->nChunksPerBlock;
+			int realignedChunk = chunk - dev->chunkOffset;
+
+			dev->readChunkWithTagsFromNAND(dev, realignedChunk,
+					NULL, &tags);
+			T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
+				i, tags.objectId, tags.sequenceNumber, tags.eccResult));
+
+			if (tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) {
+				/* Right kind of block */
+				dev->checkpointNextBlock = tags.objectId;
+				dev->checkpointCurrentBlock = i;
+				dev->checkpointBlockList[dev->blocksInCheckpoint] = i;
+				dev->blocksInCheckpoint++;
+				T(YAFFS_TRACE_CHECKPOINT, (TSTR("found checkpt block %d"TENDSTR), i));
+				return;
+			}
+		}
+
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("found no more checkpt blocks"TENDSTR)));
+
+	dev->checkpointNextBlock = -1;
+	dev->checkpointCurrentBlock = -1;
+}
+
+
+int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
+{
+
+	/* Got the functions we need? */
+	if (!dev->writeChunkWithTagsToNAND ||
+			!dev->readChunkWithTagsFromNAND ||
+			!dev->eraseBlockInNAND ||
+			!dev->markNANDBlockBad)
+		return 0;
+
+	if (forWriting && !yaffs_CheckpointSpaceOk(dev))
+		return 0;
+
+	if (!dev->checkpointBuffer)
+		dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
+	if (!dev->checkpointBuffer)
+		return 0;
+
+
+	dev->checkpointPageSequence = 0;
+
+	dev->checkpointOpenForWrite = forWriting;
+
+	dev->checkpointByteCount = 0;
+	dev->checkpointSum = 0;
+	dev->checkpointXor = 0;
+	dev->checkpointCurrentBlock = -1;
+	dev->checkpointCurrentChunk = -1;
+	dev->checkpointNextBlock = dev->internalStartBlock;
+
+	/* Erase all the blocks in the checkpoint area */
+	if (forWriting) {
+		memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);
+		dev->checkpointByteOffset = 0;
+		return yaffs_CheckpointErase(dev);
+	} else {
+		int i;
+		/* Set to a value that will kick off a read */
+		dev->checkpointByteOffset = dev->nDataBytesPerChunk;
+		/* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully)
+		 * going to be way more than we need */
+		dev->blocksInCheckpoint = 0;
+		dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2;
+		dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks);
+		for (i = 0; i < dev->checkpointMaxBlocks; i++)
+			dev->checkpointBlockList[i] = -1;
+	}
+
+	return 1;
+}
+
+int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
+{
+	__u32 compositeSum;
+	compositeSum =  (dev->checkpointSum << 8) | (dev->checkpointXor & 0xFF);
+	*sum = compositeSum;
+	return 1;
+}
+
+static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
+{
+	int chunk;
+	int realignedChunk;
+
+	yaffs_ExtendedTags tags;
+
+	if (dev->checkpointCurrentBlock < 0) {
+		yaffs_CheckpointFindNextErasedBlock(dev);
+		dev->checkpointCurrentChunk = 0;
+	}
+
+	if (dev->checkpointCurrentBlock < 0)
+		return 0;
+
+	tags.chunkDeleted = 0;
+	tags.objectId = dev->checkpointNextBlock; /* Hint to next place to look */
+	tags.chunkId = dev->checkpointPageSequence + 1;
+	tags.sequenceNumber =  YAFFS_SEQUENCE_CHECKPOINT_DATA;
+	tags.byteCount = dev->nDataBytesPerChunk;
+	if (dev->checkpointCurrentChunk == 0) {
+		/* First chunk we write for the block? Set block state to
+		   checkpoint */
+		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointCurrentBlock);
+		bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
+		dev->blocksInCheckpoint++;
+	}
+
+	chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk;
+
+
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
+		chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk, tags.objectId, tags.chunkId));
+
+	realignedChunk = chunk - dev->chunkOffset;
+
+	dev->writeChunkWithTagsToNAND(dev, realignedChunk,
+			dev->checkpointBuffer, &tags);
+	dev->checkpointByteOffset = 0;
+	dev->checkpointPageSequence++;
+	dev->checkpointCurrentChunk++;
+	if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) {
+		dev->checkpointCurrentChunk = 0;
+		dev->checkpointCurrentBlock = -1;
+	}
+	memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);
+
+	return 1;
+}
+
+
+int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
+{
+	int i = 0;
+	int ok = 1;
+
+
+	__u8 * dataBytes = (__u8 *)data;
+
+
+
+	if (!dev->checkpointBuffer)
+		return 0;
+
+	if (!dev->checkpointOpenForWrite)
+		return -1;
+
+	while (i < nBytes && ok) {
+		dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes;
+		dev->checkpointSum += *dataBytes;
+		dev->checkpointXor ^= *dataBytes;
+
+		dev->checkpointByteOffset++;
+		i++;
+		dataBytes++;
+		dev->checkpointByteCount++;
+
+
+		if (dev->checkpointByteOffset < 0 ||
+		   dev->checkpointByteOffset >= dev->nDataBytesPerChunk)
+			ok = yaffs_CheckpointFlushBuffer(dev);
+	}
+
+	return i;
+}
+
+int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
+{
+	int i = 0;
+	int ok = 1;
+	yaffs_ExtendedTags tags;
+
+
+	int chunk;
+	int realignedChunk;
+
+	__u8 *dataBytes = (__u8 *)data;
+
+	if (!dev->checkpointBuffer)
+		return 0;
+
+	if (dev->checkpointOpenForWrite)
+		return -1;
+
+	while (i < nBytes && ok) {
+
+
+		if (dev->checkpointByteOffset < 0 ||
+			dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
+
+			if (dev->checkpointCurrentBlock < 0) {
+				yaffs_CheckpointFindNextCheckpointBlock(dev);
+				dev->checkpointCurrentChunk = 0;
+			}
+
+			if (dev->checkpointCurrentBlock < 0)
+				ok = 0;
+			else {
+				chunk = dev->checkpointCurrentBlock *
+					dev->nChunksPerBlock +
+					dev->checkpointCurrentChunk;
+
+				realignedChunk = chunk - dev->chunkOffset;
+
+				/* read in the next chunk */
+				/* printf("read checkpoint page %d\n",dev->checkpointPage); */
+				dev->readChunkWithTagsFromNAND(dev,
+						realignedChunk,
+						dev->checkpointBuffer,
+						&tags);
+
+				if (tags.chunkId != (dev->checkpointPageSequence + 1) ||
+					tags.eccResult > YAFFS_ECC_RESULT_FIXED ||
+					tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
+					ok = 0;
+
+				dev->checkpointByteOffset = 0;
+				dev->checkpointPageSequence++;
+				dev->checkpointCurrentChunk++;
+
+				if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
+					dev->checkpointCurrentBlock = -1;
+			}
+		}
+
+		if (ok) {
+			*dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset];
+			dev->checkpointSum += *dataBytes;
+			dev->checkpointXor ^= *dataBytes;
+			dev->checkpointByteOffset++;
+			i++;
+			dataBytes++;
+			dev->checkpointByteCount++;
+		}
+	}
+
+	return 	i;
+}
+
+int yaffs_CheckpointClose(yaffs_Device *dev)
+{
+
+	if (dev->checkpointOpenForWrite) {
+		if (dev->checkpointByteOffset != 0)
+			yaffs_CheckpointFlushBuffer(dev);
+	} else {
+		int i;
+		for (i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++) {
+			yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointBlockList[i]);
+			if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
+				bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
+			else {
+				/* Todo this looks odd... */
+			}
+		}
+		YFREE(dev->checkpointBlockList);
+		dev->checkpointBlockList = NULL;
+	}
+
+	dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock;
+	dev->nErasedBlocks -= dev->blocksInCheckpoint;
+
+
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint byte count %d" TENDSTR),
+			dev->checkpointByteCount));
+
+	if (dev->checkpointBuffer) {
+		/* free the buffer */
+		YFREE(dev->checkpointBuffer);
+		dev->checkpointBuffer = NULL;
+		return 1;
+	} else
+		return 0;
+}
+
+int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
+{
+	/* Erase the first checksum block */
+
+	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate"TENDSTR)));
+
+	if (!yaffs_CheckpointSpaceOk(dev))
+		return 0;
+
+	return yaffs_CheckpointErase(dev);
+}
+
+
+
diff -Nur linux-2.6.32.orig/fs/yaffs2/yaffs_checkptrw.h linux-2.6.32/fs/yaffs2/yaffs_checkptrw.h
--- linux-2.6.32.orig/fs/yaffs2/yaffs_checkptrw.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/yaffs_checkptrw.h	2010-01-30 20:35:01.213084831 +0100
@@ -0,0 +1,35 @@
+/*
+ * 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_CHECKPTRW_H__
+#define __YAFFS_CHECKPTRW_H__
+
+#include "yaffs_guts.h"
+
+int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting);
+
+int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
+
+int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
+
+int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
+
+int yaffs_CheckpointClose(yaffs_Device *dev);
+
+int yaffs_CheckpointInvalidateStream(yaffs_Device *dev);
+
+
+#endif
+
diff -Nur linux-2.6.32.orig/fs/yaffs2/yaffs_ecc.c linux-2.6.32/fs/yaffs2/yaffs_ecc.c
--- linux-2.6.32.orig/fs/yaffs2/yaffs_ecc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/yaffs_ecc.c	2010-01-30 20:35:01.251829837 +0100
@@ -0,0 +1,326 @@
+/*
+ * 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 General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This code implements the ECC algorithm used in SmartMedia.
+ *
+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
+ * The two unused bit are set to 1.
+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
+ * blocks are used on a 512-byte NAND page.
+ *
+ */
+
+/* Table generated by gen-ecc.c
+ * Using a table means we do not have to calculate p1..p4 and p1'..p4'
+ * for each byte of data. These are instead provided in a table in bits7..2.
+ * Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore
+ * this bytes influence on the line parity.
+ */
+
+const char *yaffs_ecc_c_version =
+	"$Id: yaffs_ecc.c,v 1.11 2009-03-06 17:20:50 wookey Exp $";
+
+#include "yportenv.h"
+
+#include "yaffs_ecc.h"
+
+static const unsigned char column_parity_table[] = {
+	0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+	0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+	0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+	0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+	0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+	0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+	0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+	0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+	0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+	0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+	0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+	0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+	0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+	0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+	0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+	0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+	0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+	0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+	0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+	0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+	0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+	0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+	0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+	0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+	0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+	0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+	0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+	0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+	0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+	0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+	0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+	0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+};
+
+/* Count the bits in an unsigned char or a U32 */
+
+static int yaffs_CountBits(unsigned char x)
+{
+	int r = 0;
+	while (x) {
+		if (x & 1)
+			r++;
+		x >>= 1;
+	}
+	return r;
+}
+
+static int yaffs_CountBits32(unsigned x)
+{
+	int r = 0;
+	while (x) {
+		if (x & 1)
+			r++;
+		x >>= 1;
+	}
+	return r;
+}
+
+/* Calculate the ECC for a 256-byte block of data */
+void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
+{
+	unsigned int i;
+
+	unsigned char col_parity = 0;
+	unsigned char line_parity = 0;
+	unsigned char line_parity_prime = 0;
+	unsigned char t;
+	unsigned char b;
+
+	for (i = 0; i < 256; i++) {
+		b = column_parity_table[*data++];
+		col_parity ^= b;
+
+		if (b & 0x01) {		/* odd number of bits in the byte */
+			line_parity ^= i;
+			line_parity_prime ^= ~i;
+		}
+	}
+
+	ecc[2] = (~col_parity) | 0x03;
+
+	t = 0;
+	if (line_parity & 0x80)
+		t |= 0x80;
+	if (line_parity_prime & 0x80)
+		t |= 0x40;
+	if (line_parity & 0x40)
+		t |= 0x20;
+	if (line_parity_prime & 0x40)
+		t |= 0x10;
+	if (line_parity & 0x20)
+		t |= 0x08;
+	if (line_parity_prime & 0x20)
+		t |= 0x04;
+	if (line_parity & 0x10)
+		t |= 0x02;
+	if (line_parity_prime & 0x10)
+		t |= 0x01;
+	ecc[1] = ~t;
+
+	t = 0;
+	if (line_parity & 0x08)
+		t |= 0x80;
+	if (line_parity_prime & 0x08)
+		t |= 0x40;
+	if (line_parity & 0x04)
+		t |= 0x20;
+	if (line_parity_prime & 0x04)
+		t |= 0x10;
+	if (line_parity & 0x02)
+		t |= 0x08;
+	if (line_parity_prime & 0x02)
+		t |= 0x04;
+	if (line_parity & 0x01)
+		t |= 0x02;
+	if (line_parity_prime & 0x01)
+		t |= 0x01;
+	ecc[0] = ~t;
+
+#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
+	/* Swap the bytes into the wrong order */
+	t = ecc[0];
+	ecc[0] = ecc[1];
+	ecc[1] = t;
+#endif
+}
+
+
+/* Correct the ECC on a 256 byte block of data */
+
+int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
+		     const unsigned char *test_ecc)
+{
+	unsigned char d0, d1, d2;	/* deltas */
+
+	d0 = read_ecc[0] ^ test_ecc[0];
+	d1 = read_ecc[1] ^ test_ecc[1];
+	d2 = read_ecc[2] ^ test_ecc[2];
+
+	if ((d0 | d1 | d2) == 0)
+		return 0; /* no error */
+
+	if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
+	    ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
+	    ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
+		/* Single bit (recoverable) error in data */
+
+		unsigned byte;
+		unsigned bit;
+
+#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
+		/* swap the bytes to correct for the wrong order */
+		unsigned char t;
+
+		t = d0;
+		d0 = d1;
+		d1 = t;
+#endif
+
+		bit = byte = 0;
+
+		if (d1 & 0x80)
+			byte |= 0x80;
+		if (d1 & 0x20)
+			byte |= 0x40;
+		if (d1 & 0x08)
+			byte |= 0x20;
+		if (d1 & 0x02)
+			byte |= 0x10;
+		if (d0 & 0x80)
+			byte |= 0x08;
+		if (d0 & 0x20)
+			byte |= 0x04;
+		if (d0 & 0x08)
+			byte |= 0x02;
+		if (d0 & 0x02)
+			byte |= 0x01;
+
+		if (d2 & 0x80)
+			bit |= 0x04;
+		if (d2 & 0x20)
+			bit |= 0x02;
+		if (d2 & 0x08)
+			bit |= 0x01;
+
+		data[byte] ^= (1 << bit);
+
+		return 1; /* Corrected the error */
+	}
+
+	if ((yaffs_CountBits(d0) +
+	     yaffs_CountBits(d1) +
+	     yaffs_CountBits(d2)) ==  1) {
+		/* Reccoverable error in ecc */
+
+		read_ecc[0] = test_ecc[0];
+		read_ecc[1] = test_ecc[1];
+		read_ecc[2] = test_ecc[2];
+
+		return 1; /* Corrected the error */
+	}
+
+	/* Unrecoverable error */
+
+	return -1;
+
+}
+
+
+/*
+ * ECCxxxOther does ECC calcs on arbitrary n bytes of data
+ */
+void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
+				yaffs_ECCOther *eccOther)
+{
+	unsigned int i;
+
+	unsigned char col_parity = 0;
+	unsigned line_parity = 0;
+	unsigned line_parity_prime = 0;
+	unsigned char b;
+
+	for (i = 0; i < nBytes; i++) {
+		b = column_parity_table[*data++];
+		col_parity ^= b;
+
+		if (b & 0x01)	 {
+			/* odd number of bits in the byte */
+			line_parity ^= i;
+			line_parity_prime ^= ~i;
+		}
+
+	}
+
+	eccOther->colParity = (col_parity >> 2) & 0x3f;
+	eccOther->lineParity = line_parity;
+	eccOther->lineParityPrime = line_parity_prime;
+}
+
+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
+			yaffs_ECCOther *read_ecc,
+			const yaffs_ECCOther *test_ecc)
+{
+	unsigned char cDelta;	/* column parity delta */
+	unsigned lDelta;	/* line parity delta */
+	unsigned lDeltaPrime;	/* line parity delta */
+	unsigned bit;
+
+	cDelta = read_ecc->colParity ^ test_ecc->colParity;
+	lDelta = read_ecc->lineParity ^ test_ecc->lineParity;
+	lDeltaPrime = read_ecc->lineParityPrime ^ test_ecc->lineParityPrime;
+
+	if ((cDelta | lDelta | lDeltaPrime) == 0)
+		return 0; /* no error */
+
+	if (lDelta == ~lDeltaPrime &&
+	    (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) {
+		/* Single bit (recoverable) error in data */
+
+		bit = 0;
+
+		if (cDelta & 0x20)
+			bit |= 0x04;
+		if (cDelta & 0x08)
+			bit |= 0x02;
+		if (cDelta & 0x02)
+			bit |= 0x01;
+
+		if (lDelta >= nBytes)
+			return -1;
+
+		data[lDelta] ^= (1 << bit);
+
+		return 1; /* corrected */
+	}
+
+	if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
+			yaffs_CountBits(cDelta)) == 1) {
+		/* Reccoverable error in ecc */
+
+		*read_ecc = *test_ecc;
+		return 1; /* corrected */
+	}
+
+	/* Unrecoverable error */
+
+	return -1;
+}
diff -Nur linux-2.6.32.orig/fs/yaffs2/yaffs_ecc.h linux-2.6.32/fs/yaffs2/yaffs_ecc.h
--- linux-2.6.32.orig/fs/yaffs2/yaffs_ecc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/yaffs_ecc.h	2010-01-30 20:35:01.292693842 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+/*
+ * This code implements the ECC algorithm used in SmartMedia.
+ *
+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
+ * The two unused bit are set to 1.
+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
+ * blocks are used on a 512-byte NAND page.
+ *
+ */
+
+#ifndef __YAFFS_ECC_H__
+#define __YAFFS_ECC_H__
+
+typedef struct {
+	unsigned char colParity;
+	unsigned lineParity;
+	unsigned lineParityPrime;
+} yaffs_ECCOther;
+
+void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);
+int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
+		const unsigned char *test_ecc);
+
+void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
+			yaffs_ECCOther *ecc);
+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
+			yaffs_ECCOther *read_ecc,
+			const yaffs_ECCOther *test_ecc);
+#endif
diff -Nur linux-2.6.32.orig/fs/yaffs2/yaffs_fs.c linux-2.6.32/fs/yaffs2/yaffs_fs.c
--- linux-2.6.32.orig/fs/yaffs2/yaffs_fs.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.32/fs/yaffs2/yaffs_fs.c	2010-01-30 20:35:01.331845579 +0100
@@ -0,0 +1,2529 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2009 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ * Acknowledgements:
+ * Luc van OostenRyck for numerous patches.
+ * Nick Bane for numerous patches.
+ * Nick Bane for 2.5/2.6 integration.
+ * Andras Toth for mknod rdev issue.
+ * Michael Fischer for finding the problem with inode inconsistency.
+ * Some code bodily lifted from JFFS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ *
+ * This is the file system front-end to YAFFS that hooks it up to
+ * the VFS.
+ *
+ * Special notes:
+ * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with
+ *         this superblock
+ * >> 2.6: sb->s_fs_info  points to the yaffs_Device associated with this
+ *         superblock
+ * >> inode->u.generic_ip points to the associated yaffs_Object.
+ */
+
+const char *yaffs_fs_c_version =
+    "$Id: yaffs_fs.c,v 1.79 2009-03-17 01:12:00 wookey Exp $";
+extern const char *yaffs_guts_c_version;
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
+#include <linux/config.h>
+#endif
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+#include <linux/pagemap.h>
+#include <linux/mtd/mtd.h>
+#include <linux/interrupt.h>
+#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 */
+#include <linux/statfs.h>
+#define UnlockPage(p) unlock_page(p)
+#define Page_Uptodate(page)	test_bit(PG_uptodate, &(page)->flags)
+
+/* FIXME: use sb->s_id instead ? */
+#define yaffs_devname(sb, buf)	bdevname(sb->s_bdev, buf)
+
+#else
+
+#include <linux/locks.h>
+#define	BDEVNAME_SIZE		0
+#define	yaffs_devname(sb, buf)	kdevname(sb->s_dev)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
+/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
+#define __user
+#endif
+
+#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)
+#else
+#define WRITE_SIZE_STR "oobblock"
+#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
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
+static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
+{
+	uint64_t result = partition_size;
+	do_div(result, block_size);
+	return (uint32_t)result;
+}
+#else
+#define YCALCBLOCKS(s, b) ((s)/(b))
+#endif
+
+#include <linux/uaccess.h>
+
+#include "yportenv.h"
+#include "yaffs_guts.h"
+
+#include <linux/mtd/mtd.h>
+#include "yaffs_mtdif.h"
+#include "yaffs_mtdif1.h"
+#include "yaffs_mtdif2.h"
+
+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 */
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
+#define yaffs_InodeToObjectLV(iptr) ((iptr)->i_private)
+#else
+#define yaffs_InodeToObjectLV(iptr) ((iptr)->u.generic_ip)
+#endif
+
+#define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr)))
+#define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode)
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#define yaffs_SuperToDevice(sb)	((yaffs_Device *)sb->s_fs_info)
+#else
+#define yaffs_SuperToDevice(sb)	((yaffs_Device *)sb->u.generic_sbp)
+#endif
+
+static void yaffs_put_super(struct super_block *sb);
+
+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);
+#else
+static int yaffs_file_flush(struct file *file);
+#endif
+
+static int yaffs_sync_object(struct file *file, struct dentry *dentry,
+				int datasync);
+
+static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
+			struct nameidata *n);
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
+					struct nameidata *n);
+#else
+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry);
+#endif
+static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
+			struct dentry *dentry);
+static int yaffs_unlink(struct inode *dir, struct dentry *dentry);
+static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
+			const char *symname);
+static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+			dev_t dev);
+#else
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+			int dev);
+#endif
+static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+			struct inode *new_dir, struct dentry *new_dentry);
+static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_sync_fs(struct super_block *sb, int wait);
+static void yaffs_write_super(struct super_block *sb);
+#else
+static int yaffs_sync_fs(struct super_block *sb);
+static int yaffs_write_super(struct super_block *sb);
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);
+#else
+static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
+#endif
+
+#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 *);
+
+static int yaffs_readpage(struct file *file, struct page *page);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_writepage(struct page *page, struct writeback_control *wbc);
+#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);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
+#else
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
+#endif
+
+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))
+static const struct file_operations yaffs_file_operations = {
+	.read = do_sync_read,
+	.write = do_sync_write,
+	.aio_read = generic_file_aio_read,
+	.aio_write = generic_file_aio_write,
+	.mmap = generic_file_mmap,
+	.flush = yaffs_file_flush,
+	.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))
+
+static const struct file_operations yaffs_file_operations = {
+	.read = do_sync_read,
+	.write = do_sync_write,
+	.aio_read = generic_file_aio_read,
+	.aio_write = generic_file_aio_write,
+	.mmap = generic_file_mmap,
+	.flush = yaffs_file_flush,
+	.fsync = yaffs_sync_object,
+	.sendfile = generic_file_sendfile,
+};
+
+#else
+
+static const struct file_operations yaffs_file_operations = {
+	.read = generic_file_read,
+	.write = generic_file_write,
+	.mmap = generic_file_mmap,
+	.flush = yaffs_file_flush,
+	.fsync = yaffs_sync_object,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+	.sendfile = generic_file_sendfile,
+#endif
+};
+#endif
+
+static const struct inode_operations yaffs_file_inode_operations = {
+	.setattr = yaffs_setattr,
+};
+
+static const struct inode_operations yaffs_symlink_inode_operations = {
+	.readlink = yaffs_readlink,
+	.follow_link = yaffs_follow_link,
+	.setattr = yaffs_setattr,
+};
+
+static const struct inode_operations yaffs_dir_inode_operations = {
+	.create = yaffs_create,
+	.lookup = yaffs_lookup,
+	.link = yaffs_link,
+	.unlink = yaffs_unlink,
+	.symlink = yaffs_symlink,
+	.mkdir = yaffs_mkdir,
+	.rmdir = yaffs_unlink,
+	.mknod = yaffs_mknod,
+	.rename = yaffs_rename,
+	.setattr = yaffs_setattr,
+};
+
+static const struct file_operations yaffs_dir_operations = {
+	.read = generic_read_dir,
+	.readdir = yaffs_readdir,
+	.fsync = yaffs_sync_object,
+};
+
+static const 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,
+	.sync_fs = yaffs_sync_fs,
+	.write_super = yaffs_write_super,
+};
+
+static void yaffs_GrossLock(yaffs_Device *dev)
+{
+	T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current));
+	down(&dev->grossLock);
+	T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current));
+}
+
+static void yaffs_GrossUnlock(yaffs_Device *dev)
+{
+	T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));
+	up(&dev->grossLock);
+}
+
+static int yaffs_readlink(struct dentry *dentry, char __user *buffer,
+			int buflen)
+{
+	unsigned char *alias;
+	int ret;
+
+	yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
+
+	yaffs_GrossLock(dev);
+
+	alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
+
+	yaffs_GrossUnlock(dev);
+
+	if (!alias)
+		return -ENOMEM;
+
+	ret = vfs_readlink(dentry, buffer, buflen, alias);
+	kfree(alias);
+	return ret;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+#else
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+#endif
+{
+	unsigned char *alias;
+	int ret;
+	yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
+
+	yaffs_GrossLock(dev);
+
+	alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
+
+	yaffs_GrossUnlock(dev);
+
+	if (!alias) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = vfs_follow_link(nd, alias);
+	kfree(alias);
+out:
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
+	return ERR_PTR(ret);
+#else
+	return ret;
+#endif
+}
+
+struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
+				yaffs_Object *obj);
+
+/*
+ * Lookup is used to find objects in the fs
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
+				struct nameidata *n)
+#else
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
+#endif
+{
+	yaffs_Object *obj;
+	struct inode *inode = NULL;	/* NCB 2.5/2.6 needs NULL here */
+
+	yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
+
+	yaffs_GrossLock(dev);
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_lookup for %d:%s\n",
+		yaffs_InodeToObject(dir)->objectId, dentry->d_name.name));
+
+	obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),
+					dentry->d_name.name);
+
+	obj = yaffs_GetEquivalentObject(obj);	/* in case it was a hardlink */
+
+	/* Can't hold gross lock when calling yaffs_get_inode() */
+	yaffs_GrossUnlock(dev);
+
+	if (obj) {
+		T(YAFFS_TRACE_OS,
+			("yaffs_lookup found %d\n", obj->objectId));
+
+		inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
+
+		if (inode) {
+			T(YAFFS_TRACE_OS,
+				("yaffs_loookup dentry \n"));
+/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
+ * d_add even if NULL inode */
+#if 0
+			/*dget(dentry); // try to solve directory bug */
+			d_add(dentry, inode);
+
+			/* return dentry; */
+			return NULL;
+#endif
+		}
+
+	} else {
+		T(YAFFS_TRACE_OS, ("yaffs_lookup not found\n"));
+
+	}
+
+/* added NCB for 2.5/6 compatability - forces add even if inode is
+ * NULL which creates dentry hash */
+	d_add(dentry, inode);
+
+	return NULL;
+}
+
+
+#ifdef YAFFS_HAS_PUT_INODE
+
+/* For now put inode is just for debugging
+ * Put inode is called when the inode **structure** is put.
+ */
+static void yaffs_put_inode(struct inode *inode)
+{
+	T(YAFFS_TRACE_OS,
+		("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino,
+		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)
+{
+	yaffs_Object *obj;
+	yaffs_Device *dev;
+
+	obj = yaffs_InodeToObject(inode);
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino,
+		atomic_read(&inode->i_count),
+		obj ? "object exists" : "null object"));
+
+	if (obj) {
+		dev = obj->myDev;
+		yaffs_GrossLock(dev);
+
+		/* Clear the association between the inode and
+		 * the yaffs_Object.
+		 */
+		obj->myInode = NULL;
+		yaffs_InodeToObjectLV(inode) = NULL;
+
+		/* If the object freeing was deferred, then the real
+		 * free happens now.
+		 * This should fix the inode inconsistency problem.
+		 */
+
+		yaffs_HandleDeferedFree(obj);
+
+		yaffs_GrossUnlock(dev);
+	}
+
+}
+
+/* delete is called when the link count is zero and the inode
+ * is put (ie. nobody wants to know about it anymore, time to
+ * delete the file).
+ * NB Must call clear_inode()
+ */
+static void yaffs_delete_inode(struct inode *inode)
+{
+	yaffs_Object *obj = yaffs_InodeToObject(inode);
+	yaffs_Device *dev;
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino,
+		atomic_read(&inode->i_count),
+		obj ? "object exists" : "null object"));
+
+	if (obj) {
+		dev = obj->myDev;
+		yaffs_GrossLock(dev);
+		yaffs_DeleteObject(obj);
+		yaffs_GrossUnlock(dev);
+	}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
+	truncate_inode_pages(&inode->i_data, 0);
+#endif
+	clear_inode(inode);
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_file_flush(struct file *file, fl_owner_t id)
+#else
+static int yaffs_file_flush(struct file *file)
+#endif
+{
+	yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry);
+
+	yaffs_Device *dev = obj->myDev;
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_file_flush object %d (%s)\n", obj->objectId,
+		obj->dirty ? "dirty" : "clean"));
+
+	yaffs_GrossLock(dev);
+
+	yaffs_FlushFile(obj, 1);
+
+	yaffs_GrossUnlock(dev);
+
+	return 0;
+}
+
+static int yaffs_readpage_nolock(struct file *f, struct page *pg)
+{
+	/* Lifted from jffs2 */
+
+	yaffs_Object *obj;
+	unsigned char *pg_buf;
+	int ret;
+
+	yaffs_Device *dev;
+
+	T(YAFFS_TRACE_OS, ("yaffs_readpage at %08x, size %08x\n",
+			(unsigned)(pg->index << PAGE_CACHE_SHIFT),
+			(unsigned)PAGE_CACHE_SIZE));
+
+	obj = yaffs_DentryToObject(f->f_dentry);
+
+	dev = obj->myDev;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+	BUG_ON(!PageLocked(pg));
+#else
+	if (!PageLocked(pg))
+		PAGE_BUG(pg);
+#endif
+
+	pg_buf = kmap(pg);
+	/* FIXME: Can kmap fail? */
+
+	yaffs_GrossLock(dev);
+
+	ret = yaffs_ReadDataFromFile(obj, pg_buf,
+				pg->index << PAGE_CACHE_SHIFT,
+				PAGE_CACHE_SIZE);
+
+	yaffs_GrossUnlock(dev);
+
+	if (ret >= 0)
+		ret = 0;
+
+	if (ret) {
+		ClearPageUptodate(pg);
+		SetPageError(pg);
+	} else {
+		SetPageUptodate(pg);
+		ClearPageError(pg);
+	}
+
+	flush_dcache_page(pg);
+	kunmap(pg);
+
+	T(YAFFS_TRACE_OS, ("yaffs_readpage done\n"));
+	return ret;
+}
+
+static int yaffs_readpage_unlock(struct file *f, struct page *pg)
+{
+	int ret = yaffs_readpage_nolock(f, pg);
+	UnlockPage(pg);
+	return ret;
+}
+
+static int yaffs_readpage(struct file *f, struct page *pg)
+{
+	return yaffs_readpage_unlock(f, pg);
+}
+
+/* writepage inspired by/stolen from smbfs */
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
+#else
+static int yaffs_writepage(struct page *page)
+#endif
+{
+	struct address_space *mapping = page->mapping;
+	loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
+	struct inode *inode;
+	unsigned long end_index;
+	char *buffer;
+	yaffs_Object *obj;
+	int nWritten = 0;
+	unsigned nBytes;
+
+	if (!mapping)
+		BUG();
+	inode = mapping->host;
+	if (!inode)
+		BUG();
+
+	if (offset > inode->i_size) {
+		T(YAFFS_TRACE_OS,
+			("yaffs_writepage at %08x, inode size = %08x!!!\n",
+			(unsigned)(page->index << PAGE_CACHE_SHIFT),
+			(unsigned)inode->i_size));
+		T(YAFFS_TRACE_OS,
+			("                -> don't care!!\n"));
+		unlock_page(page);
+		return 0;
+	}
+
+	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
+
+	/* easy case */
+	if (page->index < end_index)
+		nBytes = PAGE_CACHE_SIZE;
+	else
+		nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
+
+	get_page(page);
+
+	buffer = kmap(page);
+
+	obj = yaffs_InodeToObject(inode);
+	yaffs_GrossLock(obj->myDev);
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_writepage at %08x, size %08x\n",
+		(unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));
+	T(YAFFS_TRACE_OS,
+		("writepag0: obj = %05x, ino = %05x\n",
+		(int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
+
+	nWritten = yaffs_WriteDataToFile(obj, buffer,
+			page->index << PAGE_CACHE_SHIFT, nBytes, 0);
+
+	T(YAFFS_TRACE_OS,
+		("writepag1: obj = %05x, ino = %05x\n",
+		(int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
+
+	yaffs_GrossUnlock(obj->myDev);
+
+	kunmap(page);
+	SetPageUptodate(page);
+	UnlockPage(page);
+	put_page(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, ("start yaffs_write_begin\n"));
+	/* Get a page */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)
+	pg = grab_cache_page_write_begin(mapping, index, flags);
+#else
+	pg = __grab_cache_page(mapping, index);
+#endif
+
+	*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, ("end yaffs_write_begin - ok\n"));
+
+	return 0;
+
+out:
+	T(YAFFS_TRACE_OS, ("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)
+{
+	T(YAFFS_TRACE_OS, ("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;
+	uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
+
+	kva = kmap(pg);
+	addr = kva + offset_into_page;
+
+	T(YAFFS_TRACE_OS,
+		("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,
+			("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, *kva;
+
+	loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
+	int nBytes = to - offset;
+	int nWritten;
+
+	unsigned spos = pos;
+	unsigned saddr;
+
+	kva = kmap(pg);
+	addr = kva + offset;
+
+	saddr = (unsigned) addr;
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_commit_write addr %x pos %x nBytes %d\n",
+		saddr, spos, nBytes));
+
+	nWritten = yaffs_file_write(f, addr, nBytes, &pos);
+
+	if (nWritten != nBytes) {
+		T(YAFFS_TRACE_OS,
+			("yaffs_commit_write not same size nWritten %d  nBytes %d\n",
+			nWritten, nBytes));
+		SetPageError(pg);
+		ClearPageUptodate(pg);
+	} else {
+		SetPageUptodate(pg);
+	}
+
+	kunmap(pg);
+
+	T(YAFFS_TRACE_OS,
+		("yaffs_commit_write returning %d\n",
+		nWritten == nBytes ? 0 : nWritten));
+
+	return nWritten == nBytes ? 0 : nWritten;
+}
+#endif
+
+
+static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
+{
+	if (inode && obj) {
+
+
+		/* Check mode against the variant type and attempt to repair if broken. */
+		__u32 mode = obj->yst_mode;
+		switch (obj->variantType) {
+		case YAFFS_OBJECT_TYPE_FILE:
+			if (!S_ISREG(mode)) {
+				obj->yst_mode &= ~S_IFMT;
+				obj->yst_mode |= S_IFREG;
+			}
+
+			break;
+		case YAFFS_OBJECT_TYPE_SYMLINK:
+			if (!S_ISLNK(mode)) {
+				obj->yst_mode &= ~S_IFMT;
+				obj->yst_mode |= S_IFLNK;
+			}
+
+			break;
+		case YAFFS_OBJECT_TYPE_DIRECTORY:
+			if (!S_ISDIR(mode)) {
+				obj->yst_mode &= ~S_IFMT;
+				obj->yst_mode |= S_IFDIR;
+			}
+
+			break;
+		case YAFFS_OBJECT_TYPE_UNKNOWN:
+		case YAFFS_OBJECT_TYPE_HARDLINK:
+		case YAFFS_OBJECT_TYPE_SPECIAL:
+		default:
+			/* TODO? */
+			break;
+		}
+
+		inode->i_flags |= S_NOATIME;
+
+		inode->i_ino = obj->objectId;
+		inode->i_mode = obj->yst_mode;
+		inode->i_uid = obj->yst_uid;
+		inode->i_gid = obj->yst_gid;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
+		inode->i_blksize = inode->i_sb->s_blocksize;
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+
+		inode->i_rdev = old_decode_dev(obj->yst_rdev);
+		inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
+		inode->i_atime.tv_nsec = 0;
+		inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
+		inode->i_mtime.tv_nsec = 0;
+		inode->i_ctime.tv_sec = (time_