diff --git a/target/linux/xburst/patches-2.6.28/998-yaffs2_dists.patch b/target/linux/xburst/patches-2.6.28/998-yaffs2_dists.patch deleted file mode 100644 index de1749e20..000000000 --- a/target/linux/xburst/patches-2.6.28/998-yaffs2_dists.patch +++ /dev/null @@ -1,8842 +0,0 @@ -diff -urN linux-2.6.24.7/fs/yaffs2/Kconfig linux-2.6.24.7.new/fs/yaffs2/Kconfig ---- linux-2.6.24.7/fs/yaffs2/Kconfig 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/Kconfig 2009-04-21 15:01:02.000000000 +0200 -@@ -2,6 +2,8 @@ - # YAFFS file system configurations - # - -+menu "Yaffs2 Filesystems" -+ - config YAFFS_FS - tristate "YAFFS2 file system support" - default n -@@ -12,8 +14,8 @@ - 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. -+ To compile the YAFFS2 file system support as a module, choose M here: -+ the module will be called yaffs2. - - If unsure, say N. - -@@ -27,29 +29,11 @@ - 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. -- -- If unsure, say N. -- - config YAFFS_DOES_ECC - bool "Lets Yaffs do its own ECC" -- depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS -+ depends on YAFFS_FS && YAFFS_YAFFS1 - default n - help - This enables Yaffs to use its own ECC functions instead of using -@@ -59,12 +43,12 @@ - - 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 -+ depends on YAFFS_FS && YAFFS_DOES_ECC - 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. -+ 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. - -@@ -73,10 +57,39 @@ - depends on YAFFS_FS - default y - help -- Enable YAFFS2 support -- yaffs for >= 2K bytes per page devices -+ Enable YAFFS2 support -- yaffs for >= 2048 byte / page larger devices - - If unsure, say Y. - -+if SOC_JZ4730 || SOC_JZ4740 -+ -+choice -+ prompt "ECC type for oob area" -+ depends on YAFFS_YAFFS2 -+ default CONFIG_YAFFS_ECC_RS -+ help -+ There are 16 bytes for yaffs2 information in oob which should be checked -+ using some type of ECC. -+ -+config YAFFS_ECC_RS -+ bool "Use soft reed solomon ECC for oob area" -+ select REED_SOLOMON -+ select REED_SOLOMON_ENC8 -+ select REED_SOLOMON_DEC8 -+ help -+ The reed solomon ECC could correct 2 5-bit symbols for 16 bytes in oob. -+ It should be selected for MLC nand. -+ -+config YAFFS_ECC_HAMMING -+ bool "Use hamming ECC for oob area" -+ help -+ The hamming ECC could only correct 1 bit for 16 bytes in oob, but it's -+ a bit faster than reed solomon ECC. It should be selected for SLC nand. -+ -+endchoice -+ -+endif -+ - config YAFFS_AUTO_YAFFS2 - bool "Autoselect yaffs2 format" - depends on YAFFS_YAFFS2 -@@ -84,8 +97,7 @@ - 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). -+ will be used depending on the device page size. - - If unsure, say Y. - -@@ -109,57 +121,30 @@ - - 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" - 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 -+ Wide tnodes are only used for large 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. -+ Setting this to 'y' will force tnode width to 16 bits and make -+ large arrays slower. - - If unsure, say N. - --config YAFFS_ALWAYS_CHECK_CHUNK_ERASED -- bool "Force chunk erase check" -+config YAFFS_DISABLE_CHUNK_ERASED_CHECK -+ bool "Turn off debug chunk erase check" - depends on YAFFS_FS -- default n -+ default y - 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. -+ Enabling this turns off the test that chunks are erased in flash -+ before writing to them. This is safe, since the write verification -+ will fail. Suggest enabling the test (ie. say N) -+ during development to help debug things. - - If unsure, say Y. - -@@ -173,3 +158,10 @@ - but makes look-ups faster. - - If unsure, say Y. -+ -+config YAFFS_CHECKPOINT_RESERVED_BLOCKS -+ int 'Reserved blocks for checkpointing' -+ depends on YAFFS_FS -+ default 10 -+ -+endmenu -diff -urN linux-2.6.24.7/fs/yaffs2/Makefile linux-2.6.24.7.new/fs/yaffs2/Makefile ---- linux-2.6.24.7/fs/yaffs2/Makefile 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/Makefile 2009-04-21 15:01:02.000000000 +0200 -@@ -1,11 +1,10 @@ - # --# Makefile for the linux YAFFS filesystem routines. -+# Makefile for the linux YAFFS2 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_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 -+obj-y := yaffs2.o -+obj-$(CONFIG_YAFFS_FS) := yaffs_mtdif.o yaffs_mtdif2.o -+obj-$(CONFIG_YAFFS_FS) += yaffs_ecc.o yaffs_fs.o yaffs_guts.o -+obj-$(CONFIG_YAFFS_FS) += yaffs_packedtags2.o yaffs_qsort.o -+obj-$(CONFIG_YAFFS_FS) += yaffs_tagscompat.o yaffs_tagsvalidity.o -+obj-$(CONFIG_YAFFS_FS) += yaffs_checkptrw.o yaffs_nand.o -diff -urN linux-2.6.24.7/fs/yaffs2/devextras.h linux-2.6.24.7.new/fs/yaffs2/devextras.h ---- linux-2.6.24.7/fs/yaffs2/devextras.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/devextras.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -@@ -15,7 +15,7 @@ - - /* - * 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 -+ * Most of these are from kernel includes placed here so we can use them in - * applications. - * - */ -diff -urN linux-2.6.24.7/fs/yaffs2/moduleconfig.h linux-2.6.24.7.new/fs/yaffs2/moduleconfig.h ---- linux-2.6.24.7/fs/yaffs2/moduleconfig.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/moduleconfig.h 2009-04-21 15:01:02.000000000 +0200 -@@ -1,10 +1,10 @@ - /* -- * 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 - * -- * Created by Martin Fouts -+ * Created by Martin Fouts - * - * 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 -@@ -44,21 +44,7 @@ - - /* 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. --*/ --/* Default: Not selected */ --/* Meaning: Use older-style on-NAND data format with pageStatus byte */ --#define CONFIG_YAFFS_9BYTE_TAGS -+#define YAFFS_CHECKPOINT_RESERVED_BLOCKS 10 - - #endif /* YAFFS_OUT_OF_TREE */ - -diff -urN linux-2.6.24.7/fs/yaffs2/utils/Makefile linux-2.6.24.7.new/fs/yaffs2/utils/Makefile ---- linux-2.6.24.7/fs/yaffs2/utils/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24.7.new/fs/yaffs2/utils/Makefile 2009-04-21 15:01:02.000000000 +0200 -@@ -0,0 +1,69 @@ -+#Makefile for mkyaffs -+# -+# NB this is not yet suitable for putting into the kernel tree. -+# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -+# -+# Copyright (C) 2002 Aleph One Ltd. -+# for Toby Churchill Ltd and Brightstar Engineering -+# -+# Created by Charles Manning -+# -+# 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. -+ -+## Change or override KERNELDIR to your kernel -+#KERNELDIR = /usr/src/kernel-headers-2.4.18 -+#CFLAGS = -I$(KERNELDIR)/include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL -+ -+include ../../../.config -+ -+CFLAGS = -I../../../include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL -+CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -+CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline -+ -+ifeq ($(CONFIG_YAFFS_ECC_RS), y) -+CFLAGS+= -DCONFIG_YAFFS_ECC_RS -+endif -+ -+ifeq ($(CONFIG_YAFFS_ECC_HAMMING), y) -+CFLAGS+= -DCONFIG_YAFFS_ECC_HAMMING -+endif -+ -+ -+## Change if you are using a cross-compiler -+MAKETOOLS = #mipsel-linux- -+ -+CC=$(MAKETOOLS)gcc -+ -+COMMONLINKS = yaffs_ecc.c -+COMMONOBJS = $(COMMONLINKS:.c=.o) -+ -+ifeq ($(CONFIG_YAFFS_ECC_RS), y) -+COMMONOBJS += ssfdc_rs_ecc.o -+endif -+ -+MKYAFFSSOURCES = mkyaffsimage.c -+MKYAFFSIMAGEOBJS = $(MKYAFFSSOURCES:.c=.o) -+ -+MKYAFFS2SOURCES = mkyaffs2image.c -+MKYAFFS2LINKS = yaffs_packedtags2.c yaffs_tagsvalidity.c -+MKYAFFS2IMAGEOBJS = $(MKYAFFS2SOURCES:.c=.o) $(MKYAFFS2LINKS:.c=.o) -+ -+all: mkyaffsimage mkyaffs2image -+ -+$(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS): -+ ln -s ../$@ $@ -+ -+$(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) : %.o: %.c -+ $(CC) -c $(CFLAGS) $< -o $@ -+ -+mkyaffsimage: $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) -+ $(CC) -o $@ $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) -+ -+mkyaffs2image: $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS) -+ $(CC) -o $@ $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS) -+ -+ -+clean: -+ rm -f $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) $(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS) mkyaffsimage mkyaffs2image core -diff -urN linux-2.6.24.7/fs/yaffs2/utils/README linux-2.6.24.7.new/fs/yaffs2/utils/README ---- linux-2.6.24.7/fs/yaffs2/utils/README 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24.7.new/fs/yaffs2/utils/README 2009-04-21 15:01:02.000000000 +0200 -@@ -0,0 +1,11 @@ -+This directory contains yaffs/yaffs2 tools to make the fs image. -+ -+To build the tools, type 'make'. -+ -+To make yaffs2 image, use next command: -+ -+ $ mkyaffs2image 1 /myroot myroot.yaffs2 -+ -+To burn the yaffs2 image to the NAND, use next command: -+ -+ $ nandwrite -a -o /dev/mtd0 myroot.yaffs2 -diff -urN linux-2.6.24.7/fs/yaffs2/utils/mkyaffs2image.c linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffs2image.c ---- linux-2.6.24.7/fs/yaffs2/utils/mkyaffs2image.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffs2image.c 2009-04-21 15:01:02.000000000 +0200 -@@ -0,0 +1,738 @@ -+/* -+ * YAFFS: Yet another FFS. A NAND-flash specific file system. -+ * -+ * makeyaffsimage.c -+ * -+ * Makes a YAFFS file system image that can be used to load up a file system. -+ * -+ * Copyright (C) 2002 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+ * -+ * Created by Charles Manning -+ * -+ * 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. -+ * -+ * -+ * Nick Bane modifications flagged NCB -+ * -+ * Endian handling patches by James Ng. -+ * -+ * mkyaffs2image hacks by NCB -+ * -+ * Changes by Sergey Kubushin flagged KSI -+ * -+ */ -+ -+/* KSI: -+ * All this nightmare should be rewritten from ground up. Why save return -+ * values if nobody checks them? The read/write function returns only one -+ * error, -1. Positive return value does NOT mean read/write operation has -+ * been completed successfully. If somebody opens files, he MUST close them -+ * when they are not longer needed. Only those brave enough can write 64 -+ * bytes from a yaffs_PackedTags2 structure. The list is too long, there is -+ * enough bugs here to write a couple of thick books on how NOT to write -+ * programs... -+ * -+ * And BTW, what was one supposed to do with that file that this horror -+ * occasionally managed to generate? -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "yaffs_ecc.h" -+#include "yaffs_guts.h" -+ -+#include "yaffs_packedtags2.h" -+ -+unsigned yaffs_traceMask=0; -+ -+#define MAX_OBJECTS 100000 -+#define MAX_CHUNKSIZE 8192 -+#define MAX_SPARESIZE 256 -+ -+#define PT2_BYTES 25 -+ -+const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.1.1.1 2008-10-29 14:29:21 lhhuang Exp $"; -+ -+static int chunkSize = 2048; -+static int spareSize = 64; -+static int layout_no; -+ -+static struct nand_oobinfo oob_layout[] = { -+ /* KSI: -+ * Dummy "raw" layout - no ECC, all the bytes are free. Does NOT -+ * really work, only used for compatibility with CVS YAFFS2 that -+ * never ever worked with any stock MTD. -+ */ -+ { -+ .useecc = MTD_NANDECC_AUTOPLACE, -+ .eccbytes = 0, -+ .eccpos = {}, -+ .oobfree = { {0, 64} } -+ }, -+ /* KSI: -+ * Regular MTD AUTOPLACED ECC for large page NAND devices, the -+ * only one existing in stock MTD so far. It corresponds to layout# 1 -+ * in command line arguments. Any other layouts could be added to -+ * the list when they made their way in kernel's MTD. The structure -+ * is simply copied from kernel's drivers/mtd/nand/nand_base.c as-is. -+ */ -+ /* For 2KB pagesize NAND devices */ -+ { -+ .useecc = MTD_NANDECC_AUTOPLACE, -+ .eccbytes = 24, -+ .eccpos = { -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63}, -+ .oobfree = { {2, 38} } -+ }, -+ /* For 4KB pagesize NAND devices */ -+ { -+ .useecc = MTD_NANDECC_AUTOPLACE, -+ .eccbytes = 72, -+ .eccpos = { -+ 56, 57, 58, 59, 60, 61, 62, 63, -+ 64, 65, 66, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = { {2, 54} } -+ }, -+ /* For 4KB pagesize with 2 planes NAND devices */ -+ { -+ .useecc = MTD_NANDECC_AUTOPLACE, -+ .eccbytes = 72, -+ .eccpos = { -+ 56, 57, 58, 59, 60, 61, 62, 63, -+ 64, 65, 66, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = { {2, 54} } -+ }, -+ /* End-of-list marker */ -+ { -+ .useecc = -1, -+ } -+}; -+ -+typedef struct -+{ -+ dev_t dev; -+ ino_t ino; -+ int obj; -+} objItem; -+ -+ -+static objItem obj_list[MAX_OBJECTS]; -+static int n_obj = 0; -+static int obj_id = YAFFS_NOBJECT_BUCKETS + 1; -+ -+static int nObjects = 0, nDirectories = 0, nPages = 0; -+ -+static int outFile; -+ -+static int error; -+ -+static int convert_endian = 0; -+ -+static int obj_compare(const void *a, const void * b) -+{ -+ objItem *oa, *ob; -+ -+ oa = (objItem *)a; -+ ob = (objItem *)b; -+ -+ if(oa->dev < ob->dev) return -1; -+ if(oa->dev > ob->dev) return 1; -+ if(oa->ino < ob->ino) return -1; -+ if(oa->ino > ob->ino) return 1; -+ -+ return 0; -+} -+ -+ -+static void add_obj_to_list(dev_t dev, ino_t ino, int obj) -+{ -+ if(n_obj < MAX_OBJECTS) -+ { -+ obj_list[n_obj].dev = dev; -+ obj_list[n_obj].ino = ino; -+ obj_list[n_obj].obj = obj; -+ n_obj++; -+ qsort(obj_list,n_obj,sizeof(objItem),obj_compare); -+ -+ } -+ else -+ { -+ // oops! not enough space in the object array -+ fprintf(stderr,"Not enough space in object array\n"); -+ exit(2); -+ } -+} -+ -+ -+static int find_obj_in_list(dev_t dev, ino_t ino) -+{ -+ objItem *i = NULL; -+ objItem test; -+ -+ test.dev = dev; -+ test.ino = ino; -+ -+ if(n_obj > 0) -+ { -+ i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare); -+ } -+ -+ if(i) -+ { -+ return i->obj; -+ } -+ return -1; -+} -+ -+/* KSI: -+ * No big endian for now. This is left for a later time. The existing code -+ * is FUBAR. -+ */ -+#if 0 -+/* This little function converts a little endian tag to a big endian tag. -+ * NOTE: The tag is not usable after this other than calculating the CRC -+ * with. -+ */ -+static void little_to_big_endian(yaffs_Tags *tagsPtr) -+{ -+#if 0 // FIXME NCB -+ yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes. -+ yaffs_TagsUnion temp; -+ -+ memset(&temp, 0, sizeof(temp)); -+ // Ick, I hate magic numbers. -+ temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4); -+ temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4); -+ temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6); -+ temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6); -+ temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2); -+ temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2); -+ temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F); -+ temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6); -+ -+ // Now copy it back. -+ tags->asBytes[0] = temp.asBytes[0]; -+ tags->asBytes[1] = temp.asBytes[1]; -+ tags->asBytes[2] = temp.asBytes[2]; -+ tags->asBytes[3] = temp.asBytes[3]; -+ tags->asBytes[4] = temp.asBytes[4]; -+ tags->asBytes[5] = temp.asBytes[5]; -+ tags->asBytes[6] = temp.asBytes[6]; -+ tags->asBytes[7] = temp.asBytes[7]; -+#endif -+} -+#endif -+ -+void nandmtd2_pt2buf(unsigned char *buf, yaffs_PackedTags2 *pt) -+{ -+ int i, j = 0, k, n; -+ unsigned char pt2_byte_buf[PT2_BYTES]; -+ -+ *((unsigned int *) &pt2_byte_buf[0]) = pt->t.sequenceNumber; -+ *((unsigned int *) &pt2_byte_buf[4]) = pt->t.objectId; -+ *((unsigned int *) &pt2_byte_buf[8]) = pt->t.chunkId; -+ *((unsigned int *) &pt2_byte_buf[12]) = pt->t.byteCount; -+ pt2_byte_buf[16] = pt->ecc.colParity; -+ pt2_byte_buf[17] = pt->ecc.lineParity & 0xff; -+ pt2_byte_buf[18] = (pt->ecc.lineParity >> 8) & 0xff; -+ pt2_byte_buf[19] = (pt->ecc.lineParity >> 16) & 0xff; -+ pt2_byte_buf[20] = (pt->ecc.lineParity >> 24) & 0xff; -+ pt2_byte_buf[21] = pt->ecc.lineParityPrime & 0xff; -+ pt2_byte_buf[22] = (pt->ecc.lineParityPrime >> 8) & 0xff; -+ pt2_byte_buf[23] = (pt->ecc.lineParityPrime >> 16) & 0xff; -+ pt2_byte_buf[24] = (pt->ecc.lineParityPrime >> 24) & 0xff; -+ -+ k = oob_layout[layout_no].oobfree[j][0]; -+ n = oob_layout[layout_no].oobfree[j][1]; -+ -+ if (n == 0) { -+ fprintf(stderr, "No OOB space for tags"); -+ exit(-1); -+ } -+ -+ for (i = 0; i < PT2_BYTES; i++) { -+ if (n == 0) { -+ j++; -+ k = oob_layout[layout_no].oobfree[j][0]; -+ n = oob_layout[layout_no].oobfree[j][1]; -+ if (n == 0) { -+ fprintf(stderr, "No OOB space for tags"); -+ exit(-1); -+ } -+ } -+ buf[k++] = pt2_byte_buf[i]; -+ n--; -+ } -+} -+ -+static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) -+{ -+ yaffs_ExtendedTags t; -+ yaffs_PackedTags2 pt; -+ unsigned char spare_buf[MAX_SPARESIZE]; -+ -+ -+ error = write(outFile,data,chunkSize); -+ if(error < 0) return error; -+ -+ yaffs_InitialiseTags(&t); -+ -+ t.chunkId = chunkId; -+// t.serialNumber = 0; -+ t.serialNumber = 1; // **CHECK** -+ t.byteCount = nBytes; -+ t.objectId = objId; -+ -+ t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; -+ -+// added NCB **CHECK** -+ t.chunkUsed = 1; -+ -+/* KSI: Broken anyway -- e.g. &t is pointer to a wrong type... */ -+#if 0 -+ if (convert_endian) -+ { -+ little_to_big_endian(&t); -+ } -+#endif -+ -+ nPages++; -+ -+ yaffs_PackTags2(&pt,&t); -+ -+ memset(spare_buf, 0xff, spareSize); -+ -+ if (layout_no == 0) { -+ memcpy(spare_buf, &pt, sizeof(yaffs_PackedTags2)); -+ } else { -+ nandmtd2_pt2buf(spare_buf, &pt); -+ } -+ -+ return write(outFile,spare_buf,spareSize); -+} -+ -+#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \ -+ (((x) & 0x0000FF00) << 8 ) | \ -+ (((x) & 0x00FF0000) >> 8 ) | \ -+ (((x) & 0xFF000000) >> 24)) -+ -+#define SWAP16(x) ((((x) & 0x00FF) << 8) | \ -+ (((x) & 0xFF00) >> 8)) -+ -+/* KSI: Removed for now. TBD later when the proper util (from scratch) is written */ -+#if 0 -+// This one is easier, since the types are more standard. No funky shifts here. -+static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh) -+{ -+ oh->type = SWAP32(oh->type); // GCC makes enums 32 bits. -+ oh->parentObjectId = SWAP32(oh->parentObjectId); // int -+ oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness. -+ // name = skip. Char array. Not swapped. -+ oh->yst_mode = SWAP32(oh->yst_mode); -+#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case. -+ // In fact, WinCE would be *THE* place where this would be an issue! -+ oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]); -+ oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]); -+ oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]); -+ oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]); -+ oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]); -+#else -+ // Regular POSIX. -+ oh->yst_uid = SWAP32(oh->yst_uid); -+ oh->yst_gid = SWAP32(oh->yst_gid); -+ oh->yst_atime = SWAP32(oh->yst_atime); -+ oh->yst_mtime = SWAP32(oh->yst_mtime); -+ oh->yst_ctime = SWAP32(oh->yst_ctime); -+#endif -+ -+ oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that! -+ oh->equivalentObjectId = SWAP32(oh->equivalentObjectId); -+ // alias - char array. -+ oh->yst_rdev = SWAP32(oh->yst_rdev); -+ -+#ifdef CONFIG_YAFFS_WINCE -+ oh->win_ctime[0] = SWAP32(oh->win_ctime[0]); -+ oh->win_ctime[1] = SWAP32(oh->win_ctime[1]); -+ oh->win_atime[0] = SWAP32(oh->win_atime[0]); -+ oh->win_atime[1] = SWAP32(oh->win_atime[1]); -+ oh->win_mtime[0] = SWAP32(oh->win_mtime[0]); -+ oh->win_mtime[1] = SWAP32(oh->win_mtime[1]); -+ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -+ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -+ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -+ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -+ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -+ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -+#else -+ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -+ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -+ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -+ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -+ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -+ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -+ oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]); -+ oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]); -+ oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]); -+ oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]); -+ oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]); -+ oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]); -+#endif -+} -+#endif -+ -+static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) -+{ -+ __u8 bytes[MAX_CHUNKSIZE]; -+ -+ -+ yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes; -+ -+ memset(bytes,0xff,chunkSize); -+ -+ oh->type = t; -+ -+ oh->parentObjectId = parent; -+ -+ strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); -+ -+ -+ if(t != YAFFS_OBJECT_TYPE_HARDLINK) -+ { -+ oh->yst_mode = s->st_mode; -+ oh->yst_uid = s->st_uid; -+// NCB 12/9/02 oh->yst_gid = s->yst_uid; -+ oh->yst_gid = s->st_gid; -+ oh->yst_atime = s->st_atime; -+ oh->yst_mtime = s->st_mtime; -+ oh->yst_ctime = s->st_ctime; -+ oh->yst_rdev = s->st_rdev; -+ } -+ -+ if(t == YAFFS_OBJECT_TYPE_FILE) -+ { -+ oh->fileSize = s->st_size; -+ } -+ -+ if(t == YAFFS_OBJECT_TYPE_HARDLINK) -+ { -+ oh->equivalentObjectId = equivalentObj; -+ } -+ -+ if(t == YAFFS_OBJECT_TYPE_SYMLINK) -+ { -+ strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH); -+ } -+ -+/* KSI: FUBAR. Left for a leter time. */ -+#if 0 -+ if (convert_endian) -+ { -+ object_header_little_to_big_endian(oh); -+ } -+#endif -+ -+ return write_chunk(bytes,objId,0,0xffff); -+ -+} -+ -+ -+static int process_directory(int parent, const char *path) -+{ -+ -+ DIR *dir; -+ struct dirent *entry; -+ -+ nDirectories++; -+ -+ dir = opendir(path); -+ -+ if(dir) -+ { -+ while((entry = readdir(dir)) != NULL) -+ { -+ -+ /* Ignore . and .. */ -+ if(strcmp(entry->d_name,".") && -+ strcmp(entry->d_name,"..")) -+ { -+ char full_name[500]; -+ struct stat stats; -+ int equivalentObj; -+ int newObj; -+ -+ sprintf(full_name,"%s/%s",path,entry->d_name); -+ -+ lstat(full_name,&stats); -+ -+ if(S_ISLNK(stats.st_mode) || -+ S_ISREG(stats.st_mode) || -+ S_ISDIR(stats.st_mode) || -+ S_ISFIFO(stats.st_mode) || -+ S_ISBLK(stats.st_mode) || -+ S_ISCHR(stats.st_mode) || -+ S_ISSOCK(stats.st_mode)) -+ { -+ -+ newObj = obj_id++; -+ nObjects++; -+ -+ printf("Object %d, %s is a ",newObj,full_name); -+ -+ /* We're going to create an object for it */ -+ if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0) -+ { -+ /* we need to make a hard link */ -+ printf("hard link to object %d\n",equivalentObj); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); -+ } -+ else -+ { -+ -+ add_obj_to_list(stats.st_dev,stats.st_ino,newObj); -+ -+ if(S_ISLNK(stats.st_mode)) -+ { -+ -+ char symname[500]; -+ -+ memset(symname,0, sizeof(symname)); -+ -+ readlink(full_name,symname,sizeof(symname) -1); -+ -+ printf("symlink to \"%s\"\n",symname); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); -+ -+ } -+ else if(S_ISREG(stats.st_mode)) -+ { -+ printf("file, "); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL); -+ -+ if(error >= 0) -+ { -+ int h; -+ __u8 bytes[MAX_CHUNKSIZE]; -+ int nBytes; -+ int chunk = 0; -+ -+ h = open(full_name,O_RDONLY); -+ if(h >= 0) -+ { -+ memset(bytes,0xff,chunkSize); -+ while((nBytes = read(h,bytes,chunkSize)) > 0) -+ { -+ chunk++; -+ write_chunk(bytes,newObj,chunk,nBytes); -+ memset(bytes,0xff,chunkSize); -+ } -+ if(nBytes < 0) -+ error = nBytes; -+ -+ printf("%d data chunks written\n",chunk); -+ close(h); -+ } -+ else -+ { -+ perror("Error opening file"); -+ } -+ -+ } -+ -+ } -+ else if(S_ISSOCK(stats.st_mode)) -+ { -+ printf("socket\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISFIFO(stats.st_mode)) -+ { -+ printf("fifo\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISCHR(stats.st_mode)) -+ { -+ printf("character device\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISBLK(stats.st_mode)) -+ { -+ printf("block device\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISDIR(stats.st_mode)) -+ { -+ printf("directory\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL); -+// NCB modified 10/9/2001 process_directory(1,full_name); -+ process_directory(newObj,full_name); -+ } -+ } -+ } -+ else -+ { -+ printf(" we don't handle this type\n"); -+ } -+ } -+ } -+ /* KSI: -+ * Who is supposed to close those open directories in this -+ * recursive function, lord Byron? Stock "ulimit -n" is 1024 -+ * and e.g. stock Fedora /etc directory has more that 1024 -+ * directories... -+ */ -+ closedir(dir); -+ } -+ -+ return 0; -+ -+} -+ -+void usage(void) -+{ -+ /* ECC for oob should conform with CONFIG_YAFFS_ECC_XX when building linux kernel, but ecc -+ for oob isn't required when using BCH ECC, as oob will be corrected together with data -+ when using BCH ECC. */ -+#if defined(CONFIG_YAFFS_ECC_RS) -+ printf("Reed-solomn ECC will be used for checking 16 bytes for yaffs2 information in oob area.\n" -+ "so, CONFIG_YAFFS_ECC_RS should be selected when building linux kernel.\n"); -+#elif defined(CONFIG_YAFFS_ECC_HAMMING) -+ printf("Hamming ECC will be used for checking 16 bytes for yaffs2 information in oob area.\n" -+ "so, CONFIG_YAFFS_ECC_HAMMING should be selected when building linux kernel.\n"); -+#endif -+ -+ printf("usage: mkyaffs2image layout# dir image_file [convert]\n"); -+ printf("\n" -+ " layout# NAND OOB layout:\n" -+ " 0 - nand_oob_raw, no used, \n" -+ " 1 - nand_oob_64, for 2KB pagesize, \n" -+ " 2 - nand_oob_128, for 2KB pagesize using multiple planes or 4KB pagesize,\n" -+ " 3 - nand_oob_256, for 4KB pagesize using multiple planes\n"); -+ printf(" dir the directory tree to be converted\n"); -+ printf(" image_file the output file to hold the image\n"); -+ printf(" 'convert' make a big-endian img on a little-endian machine. BROKEN !\n"); -+ printf("\n Example:\n" -+ " mkyaffs2image 1 /nfsroot/root26 root26.yaffs2 \n" -+); -+ -+ exit(1); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ struct stat stats; -+ int i; -+ -+ printf("mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n"); -+ -+ if ((argc < 4) || (sscanf(argv[1], "%u", &layout_no) != 1)) -+ { -+ usage(); -+ } -+ -+ switch (layout_no) { -+ case 0: -+ printf("Warning: it isn't used by JZSOC!\n"); -+ break; -+ case 1: -+ chunkSize = 2048; -+ spareSize = 64; -+ break; -+ case 2: -+ chunkSize = 4096; -+ spareSize = 128; -+ break; -+ case 3: -+ chunkSize = 8192; -+ spareSize = 256; -+ break; -+ default: -+ usage(); -+ } -+ -+ i = 0; -+ -+ while (oob_layout[i].useecc != -1) -+ i++; -+ -+ if (layout_no >= i) -+ usage(); -+ -+ if ((argc == 5) && (!strncmp(argv[4], "convert", strlen("convert")))) -+ { -+ /* KSI: Broken as of now. TBD. Fail. */ -+ usage(); -+ convert_endian = 1; -+ } -+ -+ if(stat(argv[2],&stats) < 0) -+ { -+ printf("Could not stat %s\n",argv[2]); -+ exit(1); -+ } -+ -+ if(!S_ISDIR(stats.st_mode)) -+ { -+ printf(" %s is not a directory\n",argv[2]); -+ exit(1); -+ } -+ -+ outFile = open(argv[3],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE); -+ -+ -+ if(outFile < 0) -+ { -+ printf("Could not open output file %s\n",argv[3]); -+ exit(1); -+ } -+ -+ printf("Processing directory %s into image file %s\n",argv[2],argv[3]); -+ error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); -+ -+ if(error) -+ error = process_directory(YAFFS_OBJECTID_ROOT,argv[2]); -+ -+ close(outFile); -+ -+ if(error < 0) -+ { -+ perror("operation incomplete"); -+ exit(1); -+ } -+ else -+ { -+ printf("Operation complete.\n" -+ "%d objects in %d directories\n" -+ "%d NAND pages\n",nObjects, nDirectories, nPages); -+ } -+ -+ close(outFile); -+ -+ exit(0); -+} -+ -diff -urN linux-2.6.24.7/fs/yaffs2/utils/mkyaffsimage.c linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffsimage.c ---- linux-2.6.24.7/fs/yaffs2/utils/mkyaffsimage.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24.7.new/fs/yaffs2/utils/mkyaffsimage.c 2009-04-21 15:01:02.000000000 +0200 -@@ -0,0 +1,593 @@ -+/* -+ * YAFFS: Yet another FFS. A NAND-flash specific file system. -+ * -+ * makeyaffsimage.c -+ * -+ * Makes a YAFFS file system image that can be used to load up a file system. -+ * -+ * Copyright (C) 2002 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+ * -+ * Created by Charles Manning -+ * -+ * 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. -+ * -+ * -+ * Nick Bane modifications flagged NCB -+ * -+ * Endian handling patches by James Ng. -+ * -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "yaffs_ecc.h" -+#include "yaffs_guts.h" -+ -+ -+#define MAX_OBJECTS 10000 -+ -+const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; -+ -+ -+typedef struct -+{ -+ dev_t dev; -+ ino_t ino; -+ int obj; -+} objItem; -+ -+ -+static objItem obj_list[MAX_OBJECTS]; -+static int n_obj = 0; -+static int obj_id = YAFFS_NOBJECT_BUCKETS + 1; -+ -+static int nObjects, nDirectories, nPages; -+ -+static int outFile; -+ -+static int error; -+ -+static int convert_endian = 0; -+ -+static int obj_compare(const void *a, const void * b) -+{ -+ objItem *oa, *ob; -+ -+ oa = (objItem *)a; -+ ob = (objItem *)b; -+ -+ if(oa->dev < ob->dev) return -1; -+ if(oa->dev > ob->dev) return 1; -+ if(oa->ino < ob->ino) return -1; -+ if(oa->ino > ob->ino) return 1; -+ -+ return 0; -+} -+ -+ -+static void add_obj_to_list(dev_t dev, ino_t ino, int obj) -+{ -+ if(n_obj < MAX_OBJECTS) -+ { -+ obj_list[n_obj].dev = dev; -+ obj_list[n_obj].ino = ino; -+ obj_list[n_obj].obj = obj; -+ n_obj++; -+ qsort(obj_list,n_obj,sizeof(objItem),obj_compare); -+ -+ } -+ else -+ { -+ // oops! not enough space in the object array -+ fprintf(stderr,"Not enough space in object array\n"); -+ exit(2); -+ } -+} -+ -+ -+static int find_obj_in_list(dev_t dev, ino_t ino) -+{ -+ objItem *i = NULL; -+ objItem test; -+ -+ test.dev = dev; -+ test.ino = ino; -+ -+ if(n_obj > 0) -+ { -+ i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare); -+ } -+ -+ if(i) -+ { -+ return i->obj; -+ } -+ return -1; -+} -+ -+// NCB added 10/9/2002 -+static __u16 yaffs_CalcNameSum(const char *name) -+{ -+ __u16 sum = 0; -+ __u16 i = 1; -+ -+ __u8 *bname = (__u8 *)name; -+ -+ while (*bname) -+ { -+ sum += (*bname) * i; -+ i++; -+ bname++; -+ } -+ return sum; -+} -+ -+ -+static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) -+{ -+ yaffs_ECCCalculate(data , spare->ecc1); -+ yaffs_ECCCalculate(&data[256] , spare->ecc2); -+} -+ -+static void yaffs_CalcTagsECC(yaffs_Tags *tags) -+{ -+ // Todo don't do anything yet. Need to calculate ecc -+ unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes; -+ unsigned i,j; -+ unsigned ecc = 0; -+ unsigned bit = 0; -+ -+ // Clear ECC fields -+ if (!convert_endian) -+ { -+ tags->ecc = 0; -+ } -+ else -+ { -+ // Because we're in "munged tag" mode, we have to clear it manually -+ b[6] &= 0xC0; -+ b[7] &= 0x03; -+ } -+ -+ for(i = 0; i < 8; i++) -+ { -+// NCB modified 20-9-02 for(j = 1; j &0x7f; j<<=1) -+ for(j = 1; j &0xff; j<<=1) -+ { -+ bit++; -+ if(b[i] & j) -+ { -+ ecc ^= bit; -+ } -+ } -+ } -+ -+ // Write out ECC -+ if (!convert_endian) -+ { -+ tags->ecc = ecc; -+ } -+ else -+ { -+ // We have to munge the ECC again. -+ b[6] |= ((ecc >> 6) & 0x3F); -+ b[7] |= ((ecc & 0x3F) << 2); -+ } -+} -+static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr) -+{ -+ yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr; -+ -+ //yaffs_CalcTagsECC(tagsPtr); -+ -+ sparePtr->tagByte0 = tu->asBytes[0]; -+ sparePtr->tagByte1 = tu->asBytes[1]; -+ sparePtr->tagByte2 = tu->asBytes[2]; -+ sparePtr->tagByte3 = tu->asBytes[3]; -+ sparePtr->tagByte4 = tu->asBytes[4]; -+ sparePtr->tagByte5 = tu->asBytes[5]; -+ sparePtr->tagByte6 = tu->asBytes[6]; -+ sparePtr->tagByte7 = tu->asBytes[7]; -+} -+ -+/* This little function converts a little endian tag to a big endian tag. -+ * NOTE: The tag is not usable after this other than calculating the CRC -+ * with. -+ */ -+static void little_to_big_endian(yaffs_Tags *tagsPtr) -+{ -+ yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes. -+ yaffs_TagsUnion temp; -+ -+ memset(&temp, 0, sizeof(temp)); -+ // Ick, I hate magic numbers. -+ temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4); -+ temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4); -+ temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6); -+ temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6); -+ temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2); -+ temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2); -+ temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F); -+ temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6); -+ -+ // Now copy it back. -+ tags->asBytes[0] = temp.asBytes[0]; -+ tags->asBytes[1] = temp.asBytes[1]; -+ tags->asBytes[2] = temp.asBytes[2]; -+ tags->asBytes[3] = temp.asBytes[3]; -+ tags->asBytes[4] = temp.asBytes[4]; -+ tags->asBytes[5] = temp.asBytes[5]; -+ tags->asBytes[6] = temp.asBytes[6]; -+ tags->asBytes[7] = temp.asBytes[7]; -+} -+ -+static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes) -+{ -+ yaffs_Tags t; -+ yaffs_Spare s; -+ -+ error = write(outFile,data,512); -+ if(error < 0) return error; -+ -+ memset(&t,0xff,sizeof (yaffs_Tags)); -+ memset(&s,0xff,sizeof (yaffs_Spare)); -+ -+ t.chunkId = chunkId; -+ t.serialNumber = 0; -+ t.byteCount = nBytes; -+ t.objectId = objId; -+ -+ if (convert_endian) -+ { -+ little_to_big_endian(&t); -+ } -+ -+ yaffs_CalcTagsECC(&t); -+ yaffs_LoadTagsIntoSpare(&s,&t); -+ yaffs_CalcECC(data,&s); -+ -+ nPages++; -+ -+ return write(outFile,&s,sizeof(yaffs_Spare)); -+ -+} -+ -+#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \ -+ (((x) & 0x0000FF00) << 8 ) | \ -+ (((x) & 0x00FF0000) >> 8 ) | \ -+ (((x) & 0xFF000000) >> 24)) -+ -+#define SWAP16(x) ((((x) & 0x00FF) << 8) | \ -+ (((x) & 0xFF00) >> 8)) -+ -+// This one is easier, since the types are more standard. No funky shifts here. -+static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh) -+{ -+ oh->type = SWAP32(oh->type); // GCC makes enums 32 bits. -+ oh->parentObjectId = SWAP32(oh->parentObjectId); // int -+ oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness. -+ // name = skip. Char array. Not swapped. -+ oh->yst_mode = SWAP32(oh->yst_mode); -+#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case. -+ // In fact, WinCE would be *THE* place where this would be an issue! -+ oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]); -+ oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]); -+ oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]); -+ oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]); -+ oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]); -+#else -+ // Regular POSIX. -+ oh->yst_uid = SWAP32(oh->yst_uid); -+ oh->yst_gid = SWAP32(oh->yst_gid); -+ oh->yst_atime = SWAP32(oh->yst_atime); -+ oh->yst_mtime = SWAP32(oh->yst_mtime); -+ oh->yst_ctime = SWAP32(oh->yst_ctime); -+#endif -+ -+ oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that! -+ oh->equivalentObjectId = SWAP32(oh->equivalentObjectId); -+ // alias - char array. -+ oh->yst_rdev = SWAP32(oh->yst_rdev); -+ -+#ifdef CONFIG_YAFFS_WINCE -+ oh->win_ctime[0] = SWAP32(oh->win_ctime[0]); -+ oh->win_ctime[1] = SWAP32(oh->win_ctime[1]); -+ oh->win_atime[0] = SWAP32(oh->win_atime[0]); -+ oh->win_atime[1] = SWAP32(oh->win_atime[1]); -+ oh->win_mtime[0] = SWAP32(oh->win_mtime[0]); -+ oh->win_mtime[1] = SWAP32(oh->win_mtime[1]); -+ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -+ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -+ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -+ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -+ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -+ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -+#else -+ oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]); -+ oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]); -+ oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]); -+ oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]); -+ oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]); -+ oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]); -+ oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]); -+ oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]); -+ oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]); -+ oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]); -+ oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]); -+ oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]); -+#endif -+} -+ -+static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias) -+{ -+ __u8 bytes[512]; -+ -+ -+ yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes; -+ -+ memset(bytes,0xff,512); -+ -+ oh->type = t; -+ -+ oh->parentObjectId = parent; -+ -+ strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH); -+ -+ -+ if(t != YAFFS_OBJECT_TYPE_HARDLINK) -+ { -+ oh->yst_mode = s->st_mode; -+ oh->yst_uid = s->st_uid; -+// NCB 12/9/02 oh->yst_gid = s->yst_uid; -+ oh->yst_gid = s->st_gid; -+ oh->yst_atime = s->st_atime; -+ oh->yst_mtime = s->st_mtime; -+ oh->yst_ctime = s->st_ctime; -+ oh->yst_rdev = s->st_rdev; -+ } -+ -+ if(t == YAFFS_OBJECT_TYPE_FILE) -+ { -+ oh->fileSize = s->st_size; -+ } -+ -+ if(t == YAFFS_OBJECT_TYPE_HARDLINK) -+ { -+ oh->equivalentObjectId = equivalentObj; -+ } -+ -+ if(t == YAFFS_OBJECT_TYPE_SYMLINK) -+ { -+ strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH); -+ } -+ -+ if (convert_endian) -+ { -+ object_header_little_to_big_endian(oh); -+ } -+ -+ return write_chunk(bytes,objId,0,0xffff); -+ -+} -+ -+ -+static int process_directory(int parent, const char *path) -+{ -+ -+ DIR *dir; -+ struct dirent *entry; -+ -+ nDirectories++; -+ -+ dir = opendir(path); -+ -+ if(dir) -+ { -+ while((entry = readdir(dir)) != NULL) -+ { -+ -+ /* Ignore . and .. */ -+ if(strcmp(entry->d_name,".") && -+ strcmp(entry->d_name,"..")) -+ { -+ char full_name[500]; -+ struct stat stats; -+ int equivalentObj; -+ int newObj; -+ -+ sprintf(full_name,"%s/%s",path,entry->d_name); -+ -+ lstat(full_name,&stats); -+ -+ if(S_ISLNK(stats.st_mode) || -+ S_ISREG(stats.st_mode) || -+ S_ISDIR(stats.st_mode) || -+ S_ISFIFO(stats.st_mode) || -+ S_ISBLK(stats.st_mode) || -+ S_ISCHR(stats.st_mode) || -+ S_ISSOCK(stats.st_mode)) -+ { -+ -+ newObj = obj_id++; -+ nObjects++; -+ -+ printf("Object %d, %s is a ",newObj,full_name); -+ -+ /* We're going to create an object for it */ -+ if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0) -+ { -+ /* we need to make a hard link */ -+ printf("hard link to object %d\n",equivalentObj); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); -+ } -+ else -+ { -+ -+ add_obj_to_list(stats.st_dev,stats.st_ino,newObj); -+ -+ if(S_ISLNK(stats.st_mode)) -+ { -+ -+ char symname[500]; -+ -+ memset(symname,0, sizeof(symname)); -+ -+ readlink(full_name,symname,sizeof(symname) -1); -+ -+ printf("symlink to \"%s\"\n",symname); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); -+ -+ } -+ else if(S_ISREG(stats.st_mode)) -+ { -+ printf("file, "); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL); -+ -+ if(error >= 0) -+ { -+ int h; -+ __u8 bytes[512]; -+ int nBytes; -+ int chunk = 0; -+ -+ h = open(full_name,O_RDONLY); -+ if(h >= 0) -+ { -+ memset(bytes,0xff,512); -+ while((nBytes = read(h,bytes,512)) > 0) -+ { -+ chunk++; -+ write_chunk(bytes,newObj,chunk,nBytes); -+ memset(bytes,0xff,512); -+ } -+ if(nBytes < 0) -+ error = nBytes; -+ -+ printf("%d data chunks written\n",chunk); -+ } -+ else -+ { -+ perror("Error opening file"); -+ } -+ close(h); -+ -+ } -+ -+ } -+ else if(S_ISSOCK(stats.st_mode)) -+ { -+ printf("socket\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISFIFO(stats.st_mode)) -+ { -+ printf("fifo\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISCHR(stats.st_mode)) -+ { -+ printf("character device\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISBLK(stats.st_mode)) -+ { -+ printf("block device\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); -+ } -+ else if(S_ISDIR(stats.st_mode)) -+ { -+ printf("directory\n"); -+ error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL); -+// NCB modified 10/9/2001 process_directory(1,full_name); -+ process_directory(newObj,full_name); -+ } -+ } -+ } -+ else -+ { -+ printf(" we don't handle this type\n"); -+ } -+ } -+ } -+ } -+ -+ return 0; -+ -+} -+ -+ -+int main(int argc, char *argv[]) -+{ -+ struct stat stats; -+ -+ printf("mkyaffsimage: image building tool for YAFFS built "__DATE__"\n"); -+ -+ if(argc < 3) -+ { -+ printf("usage: mkyaffsimage dir image_file [convert]\n"); -+ printf(" dir the directory tree to be converted\n"); -+ printf(" image_file the output file to hold the image\n"); -+ printf(" 'convert' produce a big-endian image from a little-endian machine\n"); -+ exit(1); -+ } -+ -+ if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert")))) -+ { -+ convert_endian = 1; -+ } -+ -+ if(stat(argv[1],&stats) < 0) -+ { -+ printf("Could not stat %s\n",argv[1]); -+ exit(1); -+ } -+ -+ if(!S_ISDIR(stats.st_mode)) -+ { -+ printf(" %s is not a directory\n",argv[1]); -+ exit(1); -+ } -+ -+ outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE); -+ -+ -+ if(outFile < 0) -+ { -+ printf("Could not open output file %s\n",argv[2]); -+ exit(1); -+ } -+ -+ printf("Processing directory %s into image file %s\n",argv[1],argv[2]); -+ error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); -+ if(error) -+ error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]); -+ -+ close(outFile); -+ -+ if(error < 0) -+ { -+ perror("operation incomplete"); -+ exit(1); -+ } -+ else -+ { -+ printf("Operation complete.\n" -+ "%d objects in %d directories\n" -+ "%d NAND pages\n",nObjects, nDirectories, nPages); -+ } -+ -+ close(outFile); -+ -+ exit(0); -+} -+ -diff -urN linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.c linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.c ---- linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.c 2009-04-21 15:01:02.000000000 +0200 -@@ -0,0 +1,180 @@ -+/* Reed-Solomon decoder -+ * Copyright 2002 Phil Karn, KA9Q -+ * May be used under the terms of the GNU Lesser General Public License (LGPL) -+ */ -+#include "ssfdc_rs_ecc.h" -+ -+#include -+ -+struct CONV_DATA { -+ unsigned char shift0; -+ unsigned char mask0; -+ unsigned char mask1; -+ unsigned char merge_shift; -+} ConvData [8]= { -+ {0x0, 0xff, 0x01, 0x8}, /* 0 */ -+ {0x1, 0x7f, 0x03, 0x7}, /* 1 */ -+ {0x2, 0x3f, 0x07, 0x6}, /* 2 */ -+ {0x3, 0x1f, 0x0f, 0x5}, /* 3 */ -+ {0x4, 0x0f, 0x1f, 0x4}, /* 4 */ -+ {0x5, 0x07, 0x3f, 0x3}, /* 5 */ -+ {0x6, 0x03, 0x7f, 0x2}, /* 6 */ -+ {0x7, 0x01, 0xff, 0x1}, /* 7 */ -+}; -+ -+static void kfree(void *ptr) -+{ -+// return 0; -+} -+ -+static int modnn(struct rs *rs,int x) -+{ -+ while (x >= rs->nn) { -+ x -= rs->nn; -+ x = (x >> rs->mm) + (x & rs->nn); -+ } -+ return x; -+} -+ -+void encode_rs(void *p,data_t *data, unsigned short *bb) -+{ -+ struct rs *rs = (struct rs *)p; -+ int i, j; -+ data_t feedback; -+ -+ memset(bb,0,(rs->nroots)*sizeof(unsigned short)); -+ -+ for(i=0;i<(rs->nn)-(rs->nroots)-(rs->pad);i++){ -+ -+ feedback = (rs->index_of)[data[i] ^ bb[0]]; -+ if(feedback != ((rs->nn))){ -+ for(j=1;j<(rs->nroots);j++) -+ bb[j] ^= (rs->alpha_to)[modnn(rs,feedback + (rs->genpoly)[(rs->nroots)-j])]; -+ } -+ -+ memmove(&bb[0],&bb[1],sizeof(unsigned short)*((rs->nroots)-1)); -+ -+ if(feedback != ((rs->nn))) { -+ bb[(rs->nroots)-1] = (rs->alpha_to)[modnn(rs,feedback + (rs->genpoly)[0])]; -+ } -+ else -+ bb[(rs->nroots)-1] = 0; -+ } -+ -+} -+ -+void free_rs_int(void *p) -+{ -+ struct rs *rs = (struct rs *)p; -+ -+ free(rs->alpha_to); -+ free(rs->index_of); -+ free(rs->genpoly); -+ free(rs); -+} -+ -+/* -+ * init_rs_int - Initialize a Reed-Solomon codec -+ * @symsize: symbol size -+ * @gfpoly: Field generator polynomial coefficients -+ * @fcr: first root of RS code generator polynomial, index form -+ * @prim: primitive element to generate polynomial roots -+ * @nroots: RS code generator polynomial degree (number of roots) -+ */ -+struct rs *init_rs_int(int symsize,int gfpoly,int fcr,int prim,int nroots,int pad) -+{ -+ struct rs *rs; -+#if 0 -+ static unsigned int rs0[64]={0}; -+ static data_t alpha0[512]={0}; -+ static data_t index0[512]={0}; -+ static data_t genepoly0[9]={0}; -+#endif -+ int i, j, sr,root,iprim; -+ -+ rs = ((void *)0); -+ if(symsize < 0 || symsize > 8*sizeof(data_t)){ -+ goto done; -+ } -+ -+ if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; -+ rs->nn = (1<pad = pad; -+ rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); -+// rs->alpha_to = alpha0; -+ if(rs->alpha_to == ((void *)0)){ -+ kfree(rs); -+ rs = ((void *)0); -+ goto done; -+ } -+ rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); -+// rs->index_of = index0; -+ if(rs->index_of == ((void *)0)){ -+ kfree(rs->alpha_to); -+ kfree(rs); -+ rs = ((void *)0); -+ goto done; -+ } -+ rs->index_of[0] = ((rs->nn)); -+ rs->alpha_to[((rs->nn))] = 0; -+ sr = 1; -+ for(i=0;inn;i++){ -+ rs->index_of[sr] = i; -+ rs->alpha_to[i] = sr; -+ sr <<= 1; -+ if(sr & (1<nn; -+ } -+ if(sr != 1){ -+ kfree(rs->alpha_to); -+ kfree(rs->index_of); -+ kfree(rs); -+ rs = ((void *)0); -+ goto done; -+ } -+ rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); -+// rs->genpoly = genepoly0; -+ if(rs->genpoly == ((void *)0)){ -+ kfree(rs->alpha_to); -+ kfree(rs->index_of); -+ kfree(rs); -+ rs = ((void *)0); -+ goto done; -+ } -+ rs->fcr = fcr; -+ rs->prim = prim; -+ rs->nroots = nroots; -+ for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) -+ ; -+ rs->iprim = iprim / prim; -+ rs->genpoly[0] = 1; -+ for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { -+ rs->genpoly[i+1] = 1; -+ for (j = i; j > 0; j--){ -+ if (rs->genpoly[j] != 0) -+ rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; -+ else -+ rs->genpoly[j] = rs->genpoly[j-1]; -+ } -+ rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; -+ } -+ for (i = 0; i <= nroots; i++) -+ rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; -+ done:; -+ return rs; -+} -+ -diff -urN linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.h linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.h ---- linux-2.6.24.7/fs/yaffs2/utils/ssfdc_rs_ecc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24.7.new/fs/yaffs2/utils/ssfdc_rs_ecc.h 2009-04-21 15:01:02.000000000 +0200 -@@ -0,0 +1,29 @@ -+#ifndef __SSFDC_RS_ECC_H__ -+#define __SSFDC_RS_ECC_H__ -+ -+/* Stuff common to all the general-purpose Reed-Solomon codecs -+ * Copyright 2004 Phil Karn, KA9Q -+ * May be used under the terms of the GNU Lesser General Public License (LGPL) -+ */ -+ -+/* Reed-Solomon codec control block */ -+typedef unsigned char data_t; -+ -+struct rs { -+ int mm; /* Bits per symbol */ -+ int nn; /* Symbols per block (= (1<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) -+ 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){ -@@ -58,9 +59,9 @@ - } - } - } -- -+ - dev->blocksInCheckpoint = 0; -- -+ - return 1; - } - -@@ -72,11 +73,11 @@ - 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){ -@@ -88,7 +89,7 @@ - } - } - T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR))); -- -+ - dev->checkpointNextBlock = -1; - dev->checkpointCurrentBlock = -1; - } -@@ -97,19 +98,19 @@ - { - 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) -+ -+ 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), -+ 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; -@@ -130,7 +131,7 @@ - - int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting) - { -- -+ - /* Got the functions we need? */ - if (!dev->writeChunkWithTagsToNAND || - !dev->readChunkWithTagsFromNAND || -@@ -140,31 +141,29 @@ - - if(forWriting && !yaffs_CheckpointSpaceOk(dev)) - return 0; -- -+ - if(!dev->checkpointBuffer) - dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); - 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 */ -@@ -177,15 +176,7 @@ - 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; - } - -@@ -196,15 +187,15 @@ - 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; -@@ -217,25 +208,25 @@ - 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)); -- -+ 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->checkpointPageSequence++; - dev->checkpointCurrentChunk++; - if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){ - dev->checkpointCurrentChunk = 0; - dev->checkpointCurrentBlock = -1; - } - memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); -- -+ - return 1; - } - -@@ -245,37 +236,31 @@ - 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->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; - dev->checkpointByteOffset++; - i++; - dataBytes++; - dev->checkpointByteCount++; -- -- -+ -+ - if(dev->checkpointByteOffset < 0 || -- dev->checkpointByteOffset >= dev->nDataBytesPerChunk) -+ dev->checkpointByteOffset >= dev->nDataBytesPerChunk) - ok = yaffs_CheckpointFlushBuffer(dev); - - } -- -+ - return i; - } - -@@ -285,44 +270,41 @@ - 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 + -+ -+ 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->readChunkWithTagsFromNAND(dev, realignedChunk, - dev->checkpointBuffer, - &tags); -- -+ - if(tags.chunkId != (dev->checkpointPageSequence + 1) || - tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) - ok = 0; -@@ -330,30 +312,28 @@ - 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->checkpointOpenForWrite){ - if(dev->checkpointByteOffset != 0) - yaffs_CheckpointFlushBuffer(dev); - } else { -@@ -373,19 +353,19 @@ - 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 */ -+ /* free the buffer */ - YFREE(dev->checkpointBuffer); - dev->checkpointBuffer = NULL; - return 1; - } - else - return 0; -- -+ - } - - int yaffs_CheckpointInvalidateStream(yaffs_Device *dev) -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_checkptrw.h linux-2.6.24.7.new/fs/yaffs2/yaffs_checkptrw.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_checkptrw.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_checkptrw.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -@@ -24,8 +24,6 @@ - - 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); -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_ecc.c linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_ecc.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.c 2009-04-21 15:01:02.000000000 +0200 -@@ -14,9 +14,9 @@ - /* - * This code implements the ECC algorithm used in SmartMedia. - * -- * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -+ * 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 -+ * 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. - * - */ -@@ -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.2 2008-07-17 23:07:00 lhhuang Exp $"; - - #include "yportenv.h" - -@@ -83,17 +83,6 @@ - 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) - { -@@ -228,8 +217,8 @@ - return 1; /* Corrected the error */ - } - -- if ((yaffs_CountBits(d0) + -- yaffs_CountBits(d1) + -+ if ((yaffs_CountBits(d0) + -+ yaffs_CountBits(d1) + - yaffs_CountBits(d2)) == 1) { - /* Reccoverable error in ecc */ - -@@ -239,13 +228,115 @@ - - return 1; /* Corrected the error */ - } -- -+ - /* Unrecoverable error */ - - return -1; - - } - -+#if defined(CONFIG_YAFFS_ECC_RS) -+#ifdef __KERNEL__ -+#include -+struct rs_control *rs_decoder; -+#else -+#include "ssfdc_rs_ecc.h" -+void *rs_init_user; -+#endif -+ -+/* Transfer 16 bytes to 26 5-bit symbols */ -+void Data2Sym(const unsigned char *in, unsigned char *out) -+{ -+ int i, j, shift; -+ -+ for (i = 0; i < 26; i++){ -+ j = (5 * i) >> 3; -+ shift = (5 * i) & 0x7; -+ if (shift > 3) -+ out[i] = ((in[j] >> shift) | (in[j+1] << (8 - shift))) & 0x1f; -+ else -+ out[i] = (in[j] >> shift) & 0x1f; -+ } -+ out[25] &= 0x7; /* the last symbol has only 3 bits */ -+} -+ -+/* -+ * It does reed solomon ECC calcs on 16 bytes of oob data -+ */ -+void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, -+ yaffs_ECCOther * eccOther) -+{ -+ unsigned short *par = (unsigned short *)&eccOther->lineParity; -+ unsigned char data5[26]; -+ -+ -+ Data2Sym(data, data5); -+ memset(par, 0, 8); -+ -+#ifdef __KERNEL__ -+ /* Encode 26 symbols in data5. Store parities of 4 symbols in -+ * buffer par whose size is 8 bytes(2 bytes per symbol) */ -+ encode_rs8 (rs_decoder, data5, 26, par, 0); -+#else -+ /* init reed solomon ECC for nand oob area -+ * Symbolsize is 5 (bits) -+ * Primitive polynomial is x^5+x^2+1 -+ * first consecutive root is 0 -+ * primitive element to generate roots = 1 -+ * generator polynomial degree (number of roots) = 4 -+ * pad = (1<lineParity; -+ unsigned char data5[26]; -+ int numerr; -+ -+ Data2Sym(data, data5); -+ -+ /* Decode 26 symbols in data5. */ -+ numerr = decode_rs8 (rs_decoder, data5, par, 26, NULL, 0, NULL, 0, NULL); -+ -+ if (numerr == 0) -+ return 0; -+ else if (numerr > 0 && numerr < 3) -+ return 1; -+ else -+ return -1; -+} -+#else -+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, -+ yaffs_ECCOther * read_ecc, -+ const yaffs_ECCOther * test_ecc) -+{ -+ return 0; -+} -+#endif -+ -+#else -+ -+static int yaffs_CountBits32(unsigned x) -+{ -+ int r = 0; -+ while (x) { -+ if (x & 1) -+ r++; -+ x >>= 1; -+ } -+ return r; -+} - - /* - * ECCxxxOther does ECC calcs on arbitrary n bytes of data -@@ -293,7 +384,7 @@ - if ((cDelta | lDelta | lDeltaPrime) == 0) - return 0; /* no error */ - -- if (lDelta == ~lDeltaPrime && -+ if (lDelta == ~lDeltaPrime && - (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) - { - /* Single bit (recoverable) error in data */ -@@ -309,7 +400,7 @@ - - if(lDelta >= nBytes) - return -1; -- -+ - data[lDelta] ^= (1 << bit); - - return 1; /* corrected */ -@@ -328,4 +419,4 @@ - return -1; - - } -- -+#endif /* YAFFS_ECC_RS */ -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_ecc.h linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_ecc.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_ecc.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -@@ -16,9 +16,9 @@ - /* - * This code implements the ECC algorithm used in SmartMedia. - * -- * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -+ * 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 -+ * 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. - * - */ -@@ -32,6 +32,10 @@ - unsigned lineParityPrime; - } yaffs_ECCOther; - -+#if defined(CONFIG_YAFFS_ECC_RS) -+extern struct rs_control *rs_decoder; -+#endif -+ - 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); -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_fs.c linux-2.6.24.7.new/fs/yaffs2/yaffs_fs.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_fs.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_fs.c 2009-04-21 15:01:02.000000000 +0200 -@@ -23,7 +23,7 @@ - * This is the file system front-end to YAFFS that hooks it up to - * the VFS. - * -- * Special notes: -+ * 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 -@@ -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.2 2008-07-17 23:59:16 lhhuang Exp $"; - extern const char *yaffs_guts_c_version; - - #include -@@ -76,34 +76,23 @@ - - #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 -- - #include - - #include "yportenv.h" - #include "yaffs_guts.h" - -+unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | -+ YAFFS_TRACE_BAD_BLOCKS/* | -+ YAFFS_TRACE_CHECKPOINT*/ -+ /* | 0xFFFFFFFF */; -+ - #include - #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; -- --/* Module Parameters */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) --module_param(yaffs_traceMask,uint,0644); --module_param(yaffs_wr_attempts,uint,0644); --#else --MODULE_PARM(yaffs_traceMask,"i"); --MODULE_PARM(yaffs_wr_attempts,"i"); -+#if defined(CONFIG_YAFFS_ECC_RS) -+#include -+#include "yaffs_ecc.h" - #endif - - /*#define T(x) printk x */ -@@ -174,6 +163,8 @@ - static int yaffs_write_super(struct super_block *sb); - #endif - -+static int yaffs_remount_fs(struct super_block *, int *, char *); -+ - #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)) -@@ -213,45 +204,24 @@ - .commit_write = yaffs_commit_write, - }; - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) --static 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, --}; -- --#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) -- - static struct file_operations yaffs_file_operations = { -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) - .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 struct file_operations yaffs_file_operations = { - .read = generic_file_read, - .write = generic_file_write, -+#endif - .mmap = generic_file_mmap, - .flush = yaffs_file_flush, - .fsync = yaffs_sync_object, --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)) - .sendfile = generic_file_sendfile, - #endif -+ - }; --#endif - - static struct inode_operations yaffs_file_inode_operations = { - .setattr = yaffs_setattr, -@@ -287,6 +257,7 @@ - .read_inode = yaffs_read_inode, - .put_inode = yaffs_put_inode, - .put_super = yaffs_put_super, -+ .remount_fs = yaffs_remount_fs, - .delete_inode = yaffs_delete_inode, - .clear_inode = yaffs_clear_inode, - .sync_fs = yaffs_sync_fs, -@@ -391,7 +362,7 @@ - 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); - -@@ -429,6 +400,42 @@ - - } - -+static int yaffs_dump_dev1(yaffs_Device * dev) -+{ -+ printk("startBlock......... %d\n", dev->startBlock); -+ printk("endBlock........... %d\n", dev->endBlock); -+ printk("chunkGroupBits..... %d\n", dev->chunkGroupBits); -+ printk("chunkGroupSize..... %d\n", dev->chunkGroupSize); -+ printk("nErasedBlocks...... %d\n", dev->nErasedBlocks); -+ printk("nTnodesCreated..... %d\n", dev->nTnodesCreated); -+ printk("nFreeTnodes........ %d\n", dev->nFreeTnodes); -+ printk("nObjectsCreated.... %d\n", dev->nObjectsCreated); -+ printk("nFreeObjects....... %d\n", dev->nFreeObjects); -+ printk("nFreeChunks........ %d\n", dev->nFreeChunks); -+ printk("nPageWrites........ %d\n", dev->nPageWrites); -+ printk("nPageReads......... %d\n", dev->nPageReads); -+ printk("nBlockErasures..... %d\n", dev->nBlockErasures); -+ printk("nGCCopies.......... %d\n", dev->nGCCopies); -+ printk("garbageCollections. %d\n", dev->garbageCollections); -+ -+ printk("passiveGCs......... %d\n", dev->passiveGarbageCollections); -+ printk("nRetriedWrites..... %d\n", dev->nRetriedWrites); -+ printk("nRetireBlocks...... %d\n", dev->nRetiredBlocks); -+ printk("eccFixed........... %d\n", dev->eccFixed); -+ printk("eccUnfixed......... %d\n", dev->eccUnfixed); -+ printk("tagsEccFixed....... %d\n", dev->tagsEccFixed); -+ printk("tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed); -+ printk("cacheHits.......... %d\n", dev->cacheHits); -+ printk("nDeletedFiles...... %d\n", dev->nDeletedFiles); -+ printk("nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); -+ printk("nBackgroudDeletions %d\n", dev->nBackgroundDeletions); -+ printk("useNANDECC......... %d\n", dev->useNANDECC); -+ printk("isYaffs2........... %d\n", dev->isYaffs2); -+ -+ return 1; -+} -+ -+ - /* For now put inode is just for debugging - * Put inode is called when the inode **structure** is put. - */ -@@ -729,21 +736,21 @@ - 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 : -@@ -1020,7 +1027,7 @@ - int error = -ENOSPC; - uid_t uid = current->fsuid; - gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; -- -+ - if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) - mode |= S_ISGID; - -@@ -1075,7 +1082,7 @@ - obj = NULL; /* Do we ever get here? */ - break; - } -- -+ - /* Can not call yaffs_get_inode() with gross lock held */ - yaffs_GrossUnlock(dev); - -@@ -1264,13 +1271,13 @@ - target = - yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), - new_dentry->d_name.name); -- -- -+ -+ - - if (target && - target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && - !list_empty(&target->variant.directoryVariant.children)) { -- -+ - T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); - - retVal = YAFFS_FAIL; -@@ -1278,7 +1285,7 @@ - - /* Now does unlinking internally using shadowing mechanism */ - T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n")); -- -+ - retVal = - yaffs_RenameObject(yaffs_InodeToObject(old_dir), - old_dentry->d_name.name, -@@ -1390,7 +1397,7 @@ - - if(dev) - yaffs_CheckpointSave(dev); -- -+ - yaffs_GrossUnlock(dev); - - sb->s_dirt = 0; -@@ -1421,16 +1428,16 @@ - { - - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); -- -+ - return 0; /* yaffs_do_sync_fs(sb);*/ -- -+ - } - - - static void yaffs_read_inode(struct inode *inode) - { - /* NB This is called as a side effect of other functions, but -- * we had to release the lock to prevent deadlocks, so -+ * we had to release the lock to prevent deadlocks, so - * need to lock again. - */ - -@@ -1441,7 +1448,7 @@ - (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); - - yaffs_GrossLock(dev); -- -+ - obj = yaffs_FindObjectByNumber(dev, inode->i_ino); - - yaffs_FillInodeFromObject(inode, obj); -@@ -1451,36 +1458,34 @@ - - static LIST_HEAD(yaffs_dev_list); - --#if 0 // not used - static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) - { - yaffs_Device *dev = yaffs_SuperToDevice(sb); - - if( *flags & MS_RDONLY ) { - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; -- -+ - T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_remount_fs: %s: RO\n", dev->name )); - - yaffs_GrossLock(dev); -- -+ - yaffs_FlushEntireDeviceCache(dev); -- -+ - yaffs_CheckpointSave(dev); -- -+ - if (mtd->sync) - mtd->sync(mtd); - - yaffs_GrossUnlock(dev); - } - else { -- T(YAFFS_TRACE_OS, -+ T(YAFFS_TRACE_OS, - (KERN_DEBUG "yaffs_remount_fs: %s: RW\n", dev->name )); - } -- -+ - return 0; - } --#endif - - static void yaffs_put_super(struct super_block *sb) - { -@@ -1489,7 +1494,7 @@ - T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); - - yaffs_GrossLock(dev); -- -+ - yaffs_FlushEntireDeviceCache(dev); - - yaffs_CheckpointSave(dev); -@@ -1499,12 +1504,12 @@ - } - - yaffs_Deinitialise(dev); -- -+ - yaffs_GrossUnlock(dev); - - /* we assume this is protected by lock_kernel() in mount/umount */ - list_del(&dev->devList); -- -+ - if(dev->spareBuffer){ - YFREE(dev->spareBuffer); - dev->spareBuffer = NULL; -@@ -1530,61 +1535,12 @@ - static void yaffs_MarkSuperBlockDirty(void *vsb) - { - 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; - } - --typedef struct { -- int inband_tags; -- int skip_checkpoint_read; -- int skip_checkpoint_write; -- int no_cache; --} yaffs_options; -- --#define MAX_OPT_LEN 20 --static int yaffs_parse_options(yaffs_options *options, const char *options_str) --{ -- char cur_opt[MAX_OPT_LEN+1]; -- int p; -- int error = 0; -- -- /* Parse through the options which is a comma seperated list */ -- -- while(options_str && *options_str && !error){ -- memset(cur_opt,0,MAX_OPT_LEN+1); -- p = 0; -- -- while(*options_str && *options_str != ','){ -- if(p < MAX_OPT_LEN){ -- cur_opt[p] = *options_str; -- p++; -- } -- options_str++; -- } -- -- if(!strcmp(cur_opt,"inband-tags")) -- options->inband_tags = 1; -- else if(!strcmp(cur_opt,"no-cache")) -- options->no_cache = 1; -- else if(!strcmp(cur_opt,"no-checkpoint-read")) -- options->skip_checkpoint_read = 1; -- else if(!strcmp(cur_opt,"no-checkpoint-write")) -- options->skip_checkpoint_write = 1; -- else if(!strcmp(cur_opt,"no-checkpoint")){ -- options->skip_checkpoint_read = 1; -- options->skip_checkpoint_write = 1; -- } else { -- printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",cur_opt); -- error = 1; -- } -- -- } -- -- return error; --} -- - static struct super_block *yaffs_internal_read_super(int yaffsVersion, - struct super_block *sb, - void *data, int silent) -@@ -1596,9 +1552,6 @@ - char devname_buf[BDEVNAME_SIZE + 1]; - struct mtd_info *mtd; - int err; -- char *data_str = (char *)data; -- -- yaffs_options options; - - sb->s_magic = YAFFS_MAGIC; - sb->s_op = &yaffs_super_ops; -@@ -1614,19 +1567,6 @@ - sb->s_dev, - yaffs_devname(sb, devname_buf)); - -- if(!data_str) -- data_str = ""; -- -- printk(KERN_INFO "yaffs: passed flags \"%s\"\n",data_str); -- -- memset(&options,0,sizeof(options)); -- -- if(yaffs_parse_options(&options,data_str)){ -- /* Option parsing failed */ -- return NULL; -- } -- -- - sb->s_blocksize = PAGE_CACHE_SIZE; - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; - T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion)); -@@ -1670,14 +1610,18 @@ - T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob)); - T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad)); - T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad)); -- T(YAFFS_TRACE_OS, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd))); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize)); -+#else -+ T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock)); -+#endif - T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); - T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); -- T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); -- -+ T(YAFFS_TRACE_OS, (" size %lld\n", mtd->size)); -+ - #ifdef CONFIG_YAFFS_AUTO_YAFFS2 - -- if (yaffsVersion == 1 && -+ if (yaffsVersion == 1 && - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - mtd->writesize >= 2048) { - #else -@@ -1685,10 +1629,10 @@ - #endif - T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); - yaffsVersion = 2; -- } -- -+ } -+ - /* Added NCB 26/5/2006 for completeness */ -- if (yaffsVersion == 2 && -+ if (yaffsVersion == 2 && - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - mtd->writesize == 512) { - #else -@@ -1696,7 +1640,7 @@ - #endif - T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); - yaffsVersion = 1; -- } -+ } - - #endif - -@@ -1747,7 +1691,11 @@ - return NULL; - } - -- if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK || -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ if (mtd->writesize < YAFFS_BYTES_PER_CHUNK || -+#else -+ if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK || -+#endif - mtd->oobsize != YAFFS_BYTES_PER_SPARE) { - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device does not support have the " -@@ -1779,17 +1727,14 @@ - dev->name = mtd->name; - - /* Set up the memory size parameters.... */ -- -- nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); -- dev->startBlock = 0; -- dev->endBlock = nBlocks - 1; - dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; - dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; - dev->nReservedBlocks = 5; -- dev->nShortOpCaches = (options.no_cache) ? 0 : 10; -+ dev->nShortOpCaches = 10; /* Enable short op caching */ - - /* ... and the functions. */ - if (yaffsVersion == 2) { -+ int block_shift; - dev->writeChunkWithTagsToNAND = - nandmtd2_WriteChunkWithTagsToNAND; - dev->readChunkWithTagsFromNAND = -@@ -1805,24 +1750,18 @@ - dev->nDataBytesPerChunk = mtd->oobblock; - dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; - #endif -- nBlocks = mtd->size / mtd->erasesize; -- -+ block_shift = ffs(mtd->erasesize) - 1; -+// nBlocks = mtd->size / mtd->erasesize; -+ nBlocks = mtd->size >> block_shift; - dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS; - dev->startBlock = 0; - dev->endBlock = nBlocks - 1; - } else { --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- /* use the MTD interface in yaffs_mtdif1.c */ -- dev->writeChunkWithTagsToNAND = -- nandmtd1_WriteChunkWithTagsToNAND; -- dev->readChunkWithTagsFromNAND = -- nandmtd1_ReadChunkWithTagsFromNAND; -- dev->markNANDBlockBad = nandmtd1_MarkNANDBlockBad; -- dev->queryNANDBlock = nandmtd1_QueryNANDBlock; --#else -+ nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); -+ dev->startBlock = 0; -+ dev->endBlock = nBlocks - 1; - dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; - dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; --#endif - dev->isYaffs2 = 0; - } - /* ... and common functions */ -@@ -1830,10 +1769,10 @@ - dev->initialiseNAND = nandmtd_InitialiseNAND; - - dev->putSuperFunc = yaffs_MTDPutSuper; -- -+ - dev->superBlock = (void *)sb; - dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty; -- -+ - - #ifndef CONFIG_YAFFS_DOES_ECC - dev->useNANDECC = 1; -@@ -1843,9 +1782,6 @@ - dev->wideTnodesDisabled = 1; - #endif - -- dev->skipCheckpointRead = options.skip_checkpoint_read; -- 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); - -@@ -1858,7 +1794,7 @@ - T(YAFFS_TRACE_OS, - ("yaffs_read_super: guts initialised %s\n", - (err == YAFFS_OK) ? "OK" : "FAILED")); -- -+ - /* Release lock before yaffs_get_inode() */ - yaffs_GrossUnlock(dev); - -@@ -1869,7 +1805,6 @@ - - if (!inode) - return NULL; -- - inode->i_op = &yaffs_dir_inode_operations; - inode->i_fop = &yaffs_dir_operations; - -@@ -1884,7 +1819,6 @@ - return NULL; - } - sb->s_root = root; -- - T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n")); - return sb; - } -@@ -1990,13 +1924,9 @@ - { - buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); - buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); -- 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); - buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated); -@@ -2012,7 +1942,6 @@ - sprintf(buf, "passiveGCs......... %d\n", - dev->passiveGarbageCollections); - buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); -- buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches); - buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks); - buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed); - buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed); -@@ -2075,7 +2004,6 @@ - /** - * Set the verbosity of the warnings and error messages. - * -- * Note that the names can only be a..z or _ with the current code. - */ - - static struct { -@@ -2087,7 +2015,6 @@ - {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, - {"buffers", YAFFS_TRACE_BUFFERS}, - {"bug", YAFFS_TRACE_BUG}, -- {"checkpt", YAFFS_TRACE_CHECKPOINT}, - {"deletion", YAFFS_TRACE_DELETION}, - {"erase", YAFFS_TRACE_ERASE}, - {"error", YAFFS_TRACE_ERROR}, -@@ -2099,27 +2026,17 @@ - {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, - {"scan", YAFFS_TRACE_SCAN}, - {"tracing", YAFFS_TRACE_TRACING}, -- -- {"verify", YAFFS_TRACE_VERIFY}, -- {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, -- {"verify_full", YAFFS_TRACE_VERIFY_FULL}, -- {"verify_all", YAFFS_TRACE_VERIFY_ALL}, -- - {"write", YAFFS_TRACE_WRITE}, - {"all", 0xffffffff}, - {"none", 0}, - {NULL, 0}, - }; - --#define MAX_MASK_NAME_LENGTH 40 - static int yaffs_proc_write(struct file *file, const char *buf, - unsigned long count, void *data) - { - unsigned rg = 0, mask_bitfield; -- char *end; -- char *mask_name; -- const char *x; -- char substring[MAX_MASK_NAME_LENGTH+1]; -+ char *end, *mask_name; - int i; - int done = 0; - int add, len = 0; -@@ -2146,22 +2063,16 @@ - break; - } - mask_name = NULL; -- - mask_bitfield = simple_strtoul(buf + pos, &end, 0); - if (end > buf + pos) { - mask_name = "numeral"; - len = end - (buf + pos); -- pos += len; - done = 0; - } else { -- for(x = buf + pos, i = 0; -- (*x == '_' || (*x >='a' && *x <= 'z')) && -- i 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) - { - 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) --{ -- 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); -- } -- -- return buf ? YAFFS_OK : YAFFS_FAIL; -- --} -- - static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) - { - int i, j; -@@ -290,8 +264,6 @@ - return 0; - } - -- -- - /* - * Chunk bitmap manipulations - */ -@@ -308,16 +280,6 @@ - (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); - } - --static Y_INLINE void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk) --{ -- if(blk < dev->internalStartBlock || blk > dev->internalEndBlock || -- chunk < 0 || chunk >= dev->nChunksPerBlock) { -- T(YAFFS_TRACE_ERROR, -- (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),blk,chunk)); -- YBUG(); -- } --} -- - static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); -@@ -329,8 +291,6 @@ - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - -- yaffs_VerifyChunkBitId(dev,blk,chunk); -- - blkBits[chunk / 8] &= ~(1 << (chunk & 7)); - } - -@@ -338,16 +298,12 @@ - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - -- yaffs_VerifyChunkBitId(dev,blk,chunk); -- - blkBits[chunk / 8] |= (1 << (chunk & 7)); - } - - static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); -- yaffs_VerifyChunkBitId(dev,blk,chunk); -- - return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; - } - -@@ -363,495 +319,10 @@ - return 0; - } - --static int yaffs_CountChunkBits(yaffs_Device * dev, int blk) --{ -- __u8 *blkBits = yaffs_BlockBits(dev, blk); -- int i; -- int n = 0; -- for (i = 0; i < dev->chunkBitmapStride; i++) { -- __u8 x = *blkBits; -- while(x){ -- if(x & 1) -- 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)); --} -- --static int yaffs_SkipFullVerification(yaffs_Device *dev) --{ -- return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_FULL)); --} -- --static int yaffs_SkipNANDVerification(yaffs_Device *dev) --{ -- return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); --} -- --static const char * blockStateName[] = { --"Unknown", --"Needs scanning", --"Scanning", --"Empty", --"Allocating", --"Full", --"Dirty", --"Checkpoint", --"Collecting", --"Dead" --}; -- --static void yaffs_VerifyBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) --{ -- int actuallyUsed; -- int inUse; -- -- if(yaffs_SkipVerification(dev)) -- return; -- -- /* Report illegal runtime states */ -- if(bi->blockState <0 || 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: -- case YAFFS_BLOCK_STATE_NEEDS_SCANNING: -- 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 -- */ -- 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){ -- T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), -- n,bi->blockState)); -- } --} -- --static void yaffs_VerifyBlocks(yaffs_Device *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) -- 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))); -- -- for(i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) -- 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), -- nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING])); -- -- T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); -- --} -- --/* -- * Verify the object header. oh must be valid, but obj and tags may be NULL in which -- * case those tests will not be performed. -- */ --static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck) --{ -- if(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, -- (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), -- tags->objectId, oh->type)); -- -- if(tags->objectId != obj->objectId) -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header mismatch objectId %d"TENDSTR), -- tags->objectId, obj->objectId)); -- -- -- /* -- * 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 != 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), -- obj->objectId)); -- -- if(tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */ -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header name is 0xFF"TENDSTR), -- obj->objectId)); --} -- -- -- --static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn, -- __u32 level, int chunkOffset) --{ -- int i; -- yaffs_Device *dev = obj->myDev; -- int ok = 1; -- int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -- -- if (tn) { -- if (level > 0) { -- -- for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ -- if (tn->internal[i]) { -- ok = yaffs_VerifyTnodeWorker(obj, -- tn->internal[i], -- level - 1, -- (chunkOffset<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); -- if(tags.objectId != objectId || tags.chunkId != chunkOffset){ -- T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), -- objectId, chunkOffset, theChunk, -- tags.objectId, tags.chunkId)); -- } -- } -- chunkOffset++; -- } -- } -- } -- -- return ok; -- --} -- -- --static void yaffs_VerifyFile(yaffs_Object *obj) --{ -- int requiredTallness; -- int actualTallness; -- __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)) -- 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; -- requiredTallness = 0; -- while (x> 0) { -- 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. -- * 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); -- -- if (tn) { -- __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -- if(theChunk > 0){ -- /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */ -- yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -- if(tags.objectId != objectId || tags.chunkId != i){ -- T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), -- objectId, i, theChunk, -- tags.objectId, tags.chunkId)); -- } -- } -- } -- -- } -- --} -- --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 */ --} -- --static void yaffs_VerifySymlink(yaffs_Object *obj) --{ -- if(obj && yaffs_SkipVerification(obj->myDev)) -- return; -- -- /* Verify symlink string */ --} -- --static void yaffs_VerifySpecial(yaffs_Object *obj) --{ -- if(obj && yaffs_SkipVerification(obj->myDev)) -- return; --} -- --static void yaffs_VerifyObject(yaffs_Object *obj) --{ -- yaffs_Device *dev; -- -- __u32 chunkMin; -- __u32 chunkMax; -- -- __u32 chunkIdOk; -- __u32 chunkIsLive; -- -- if(!obj) -- 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 && -- yaffs_CheckChunkBit(dev, -- obj->chunkId / dev->nChunksPerBlock, -- obj->chunkId % dev->nChunksPerBlock); -- if(!obj->fake && -- (!chunkIdOk || !chunkIsLive)) { -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), -- obj->objectId,obj->chunkId, -- chunkIdOk ? "" : ",out of range", -- chunkIsLive || !chunkIdOk ? "" : ",marked as deleted")); -- } -- -- if(chunkIdOk && chunkIsLive &&!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_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)); -- } -- -- /* 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)); -- } -- -- switch(obj->variantType){ -- case YAFFS_OBJECT_TYPE_FILE: -- yaffs_VerifyFile(obj); -- break; -- case YAFFS_OBJECT_TYPE_SYMLINK: -- yaffs_VerifySymlink(obj); -- break; -- case YAFFS_OBJECT_TYPE_DIRECTORY: -- yaffs_VerifyDirectory(obj); -- break; -- case YAFFS_OBJECT_TYPE_HARDLINK: -- yaffs_VerifyHardLink(obj); -- break; -- case YAFFS_OBJECT_TYPE_SPECIAL: -- yaffs_VerifySpecial(obj); -- break; -- case YAFFS_OBJECT_TYPE_UNKNOWN: -- default: -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d has illegaltype %d"TENDSTR), -- 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); -- } -- } -- } -- --} -- -- - /* - * Simple hash function. Needs to have a reasonable spread - */ -- -+ - static Y_INLINE int yaffs_HashFunction(int n) - { - n = abs(n); -@@ -861,7 +332,7 @@ - /* - * Access functions to useful fake objects - */ -- -+ - yaffs_Object *yaffs_Root(yaffs_Device * dev) - { - return dev->rootDir; -@@ -876,7 +347,7 @@ - /* - * Erased NAND checking functions - */ -- -+ - int yaffs_CheckFF(__u8 * buffer, int nBytes) - { - /* Horrible, slow implementation */ -@@ -898,10 +369,10 @@ - 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,90 +386,91 @@ - - } - -- - static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, - const __u8 * data, - yaffs_ExtendedTags * tags, - int useReserve) - { -- int attempts = 0; -- int writeOk = 0; - int chunk; - -+ int writeOk = 0; -+ int erasedOk = 1; -+ int attempts = 0; -+ yaffs_BlockInfo *bi; -+ - yaffs_InvalidateCheckpoint(dev); - - do { -- yaffs_BlockInfo *bi = 0; -- int erasedOk = 0; -+ chunk = yaffs_AllocateChunk(dev, useReserve,&bi); - -- chunk = yaffs_AllocateChunk(dev, useReserve, &bi); -- if (chunk < 0) { -- /* no space */ -- break; -- } -- -- /* First check this chunk is erased, if it needs -- * checking. The checking policy (unless forced -- * always on) is as follows: -- * -- * Check the first page we try to write in a block. -- * If the check passes then we don't need to check any -- * more. If the check fails, we check again... -- * If the block has been erased, we don't need to check. -- * -- * However, if the block has been prioritised for gc, -- * then we think there might be something odd about -- * this block and stop using it. -- * -- * Rationale: We should only ever see chunks that have -- * not been erased if there was a partially written -- * chunk due to power loss. This checking policy should -- * catch that case with very few checks and thus save a -- * lot of checks that are most likely not needed. -- */ -- if (bi->gcPrioritise) { -- yaffs_DeleteChunk(dev, chunk, 1, __LINE__); -- /* try another chunk */ -- continue; -- } -+ if (chunk >= 0) { -+ /* First check this chunk is erased, if it needs checking. -+ * The checking policy (unless forced always on) is as follows: -+ * Check the first page we try to write in a block. -+ * - If the check passes then we don't need to check any more. -+ * - If the check fails, we check again... -+ * If the block has been erased, we don't need to check. -+ * -+ * However, if the block has been prioritised for gc, then -+ * we think there might be something odd about this block -+ * and stop using it. -+ * -+ * Rationale: -+ * We should only ever see chunks that have not been erased -+ * if there was a partially written chunk due to power loss -+ * This checking policy should catch that case with very -+ * few checks and thus save a lot of checks that are most likely not -+ * needed. -+ */ -+ -+ if(bi->gcPrioritise){ -+ yaffs_DeleteChunk(dev, chunk, 1, __LINE__); -+ } else { -+#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED - -- /* let's give it a try */ -- attempts++; -+ bi->skipErasedCheck = 0; - --#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED -- bi->skipErasedCheck = 0; - #endif -- if (!bi->skipErasedCheck) { -- erasedOk = yaffs_CheckChunkErased(dev, chunk); -- if (erasedOk != YAFFS_OK) { -- T(YAFFS_TRACE_ERROR, -- (TSTR ("**>> yaffs chunk %d was not erased" -- TENDSTR), chunk)); -+ if(!bi->skipErasedCheck){ -+ erasedOk = yaffs_CheckChunkErased(dev, chunk); -+ if(erasedOk && !bi->gcPrioritise) -+ bi->skipErasedCheck = 1; -+ } - -- /* try another chunk */ -- continue; -+ if (!erasedOk) { -+ T(YAFFS_TRACE_ERROR, -+ (TSTR -+ ("**>> yaffs chunk %d was not erased" -+ TENDSTR), chunk)); -+ } else { -+ writeOk = -+ yaffs_WriteChunkWithTagsToNAND(dev, chunk, -+ data, tags); -+ } -+ -+ attempts++; -+ -+ if (writeOk) { -+ /* -+ * Copy the data into the robustification buffer. -+ * NB We do this at the end to prevent duplicates in the case of a write error. -+ * Todo -+ */ -+ yaffs_HandleWriteChunkOk(dev, chunk, data, tags); -+ -+ } else { -+ /* The erased check or write failed */ -+ yaffs_HandleWriteChunkError(dev, chunk, erasedOk); -+ } - } -- bi->skipErasedCheck = 1; - } - -- writeOk = yaffs_WriteChunkWithTagsToNAND(dev, chunk, -- data, tags); -- if (writeOk != YAFFS_OK) { -- yaffs_HandleWriteChunkError(dev, chunk, erasedOk); -- /* try another chunk */ -- continue; -- } -- -- /* Copy the data into the robustification buffer */ -- yaffs_HandleWriteChunkOk(dev, chunk, data, tags); -- -- } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts); -+ } while (chunk >= 0 && !writeOk); - - if (attempts > 1) { - T(YAFFS_TRACE_ERROR, -- (TSTR("**>> yaffs write required %d attempts" TENDSTR), -- attempts)); -- -+ (TSTR("**>> yaffs write required %d attempts" TENDSTR), -+ attempts)); - dev->nRetriedWrites += (attempts - 1); - } - -@@ -1008,13 +480,13 @@ - /* - * 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 +500,7 @@ - * Functions for robustisizing TODO - * - */ -- -+ - static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, - const __u8 * data, - const yaffs_ExtendedTags * tags) -@@ -1046,13 +518,28 @@ - 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))); - - } -+ -+ } -+} - -+static void yaffs_ReportOddballBlocks(yaffs_Device *dev) -+{ -+ int i; -+ -+ for(i = dev->internalStartBlock; i <= dev->internalEndBlock && (yaffs_traceMask & YAFFS_TRACE_BAD_BLOCKS); i++){ -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -+ if(bi->needsRetiring || bi->gcPrioritise) -+ T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("yaffs block %d%s%s" TENDSTR), -+ i, -+ bi->needsRetiring ? " needs retiring" : "", -+ bi->gcPrioritise ? " gc prioritised" : "")); -+ - } - } - -@@ -1061,25 +548,22 @@ - - int blockInNAND = chunkInNAND / dev->nChunksPerBlock; - 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) - { -@@ -1088,7 +572,7 @@ - - YUCHAR *bname = (YUCHAR *) name; - if (bname) { -- while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) { -+ while ((*bname) && (i <= YAFFS_MAX_NAME_LENGTH)) { - - #ifdef CONFIG_YAFFS_CASE_INSENSITIVE - sum += yaffs_toupper(*bname) * i; -@@ -1120,7 +604,7 @@ - * 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,7 +622,7 @@ - - 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; -@@ -1175,7 +659,7 @@ - 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,13 +674,12 @@ - * NB If we can't add this to the management list it isn't fatal - * but it just means we can't free this bunch of tnodes later. - */ -- -+ - tnl = YMALLOC(sizeof(yaffs_TnodeList)); - if (!tnl) { - T(YAFFS_TRACE_ERROR, - (TSTR - ("yaffs: Could not add tnodes to management list" TENDSTR))); -- return YAFFS_FAIL; - - } else { - tnl->tnodes = newTnodes; -@@ -1239,11 +722,11 @@ - static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev) - { - yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev); -- -+ - if(tn) - memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); - -- return tn; -+ return tn; - } - - /* FreeTnode frees up a tnode and puts it back on the free list */ -@@ -1299,19 +782,19 @@ - __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++;; -@@ -1321,31 +804,31 @@ - } - } - --static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) -+__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) - { - __u32 *map = (__u32 *)tn; - __u32 bitInMap; - __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 +877,7 @@ - while (level > 0 && tn) { - tn = tn-> - internal[(chunkId >> -- ( YAFFS_TNODES_LEVEL0_BITS + -+ ( YAFFS_TNODES_LEVEL0_BITS + - (level - 1) * - YAFFS_TNODES_INTERNAL_BITS) - ) & -@@ -1416,7 +899,7 @@ - * 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 +936,7 @@ - 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 +955,7 @@ - - l = fStruct->topLevel; - tn = fStruct->top; -- -+ - if(l > 0) { - while (l > 0 && tn) { - x = (chunkId >> -@@ -1492,13 +975,13 @@ - 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 +1022,7 @@ - - /* 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 +1136,7 @@ - * 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 +1177,7 @@ - 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 +1279,7 @@ - /* 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) - */ - -@@ -1839,18 +1322,13 @@ - - /* make these things */ - newObjects = YMALLOC(nObjects * sizeof(yaffs_Object)); -- list = YMALLOC(sizeof(yaffs_ObjectList)); - -- if (!newObjects || !list) { -- if(newObjects) -- YFREE(newObjects); -- if(list) -- YFREE(list); -+ if (!newObjects) { - T(YAFFS_TRACE_ALLOCATE, - (TSTR("yaffs: Could not allocate more objects" TENDSTR))); - return YAFFS_FAIL; - } -- -+ - /* Hook them into the free list */ - for (i = 0; i < nObjects - 1; i++) { - newObjects[i].siblings.next = -@@ -1864,9 +1342,15 @@ - - /* Now add this bunch of Objects to a list for freeing up. */ - -- list->objects = newObjects; -- list->next = dev->allocatedObjectList; -- dev->allocatedObjectList = list; -+ list = YMALLOC(sizeof(yaffs_ObjectList)); -+ if (!list) { -+ T(YAFFS_TRACE_ALLOCATE, -+ (TSTR("Could not add objects to management list" TENDSTR))); -+ } else { -+ list->objects = newObjects; -+ list->next = dev->allocatedObjectList; -+ dev->allocatedObjectList = list; -+ } - - return YAFFS_OK; - } -@@ -2123,25 +1607,12 @@ - { - - yaffs_Object *theObject; -- yaffs_Tnode *tn; - - if (number < 0) { - number = yaffs_CreateNewObjectNumber(dev); - } - - theObject = yaffs_AllocateEmptyObject(dev); -- if(!theObject) -- return NULL; -- -- if(type == YAFFS_OBJECT_TYPE_FILE){ -- tn = yaffs_GetTnode(dev); -- if(!tn){ -- yaffs_FreeObject(theObject); -- return NULL; -- } -- } -- -- - - if (theObject) { - theObject->fake = 0; -@@ -2168,7 +1639,8 @@ - theObject->variant.fileVariant.scannedFileSize = 0; - theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */ - theObject->variant.fileVariant.topLevel = 0; -- theObject->variant.fileVariant.top = tn; -+ theObject->variant.fileVariant.top = -+ yaffs_GetTnode(dev); - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: - INIT_LIST_HEAD(&theObject->variant.directoryVariant. -@@ -2205,7 +1677,7 @@ - return theObject; - - } -- -+ - - static YCHAR *yaffs_CloneString(const YCHAR * str) - { -@@ -2213,8 +1685,7 @@ - - if (str && *str) { - newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); -- if(newStr) -- yaffs_strcpy(newStr, str); -+ yaffs_strcpy(newStr, str); - } - - return newStr; -@@ -2227,7 +1698,7 @@ - * 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 +1709,6 @@ - const YCHAR * aliasString, __u32 rdev) - { - yaffs_Object *in; -- YCHAR *str; - - yaffs_Device *dev = parent->myDev; - -@@ -2249,16 +1719,6 @@ - - in = yaffs_CreateNewObject(dev, -1, type); - -- if(type == YAFFS_OBJECT_TYPE_SYMLINK){ -- str = yaffs_CloneString(aliasString); -- if(!str){ -- yaffs_FreeObject(in); -- return NULL; -- } -- } -- -- -- - if (in) { - in->chunkId = -1; - in->valid = 1; -@@ -2289,7 +1749,8 @@ - - switch (type) { - case YAFFS_OBJECT_TYPE_SYMLINK: -- in->variant.symLinkVariant.alias = str; -+ in->variant.symLinkVariant.alias = -+ yaffs_CloneString(aliasString); - break; - case YAFFS_OBJECT_TYPE_HARDLINK: - in->variant.hardLinkVariant.equivalentObject = -@@ -2298,7 +1759,7 @@ - equivalentObject->objectId; - list_add(&in->hardLinks, &equivalentObject->hardLinks); - break; -- case YAFFS_OBJECT_TYPE_FILE: -+ case YAFFS_OBJECT_TYPE_FILE: - case YAFFS_OBJECT_TYPE_DIRECTORY: - case YAFFS_OBJECT_TYPE_SPECIAL: - case YAFFS_OBJECT_TYPE_UNKNOWN: -@@ -2382,7 +1843,7 @@ - TENDSTR))); - YBUG(); - } -- -+ - /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ - if (obj->myDev->isYaffs2) { - unlinkOp = (newDir == obj->myDev->unlinkedDir); -@@ -2395,9 +1856,9 @@ - - 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 || -@@ -2461,7 +1922,7 @@ - /* 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, -+ /* Nuke the target first, using shadowing, - * but only if it isn't the same object - */ - yaffs_ChangeObjectName(obj, newDir, newName, force, -@@ -2479,13 +1940,10 @@ - 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 */ -+ /* Todo we're assuming the malloc will pass. */ - dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); - if(!dev->blockInfo){ - dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); -@@ -2493,20 +1951,17 @@ - } - 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); -- if(!dev->chunkBits){ -- dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); -- dev->chunkBitsAlt = 1; -- } -- else -- dev->chunkBitsAlt = 0; -+ -+ /* Set up dynamic blockinfo stuff. */ -+ dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */ -+ dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); -+ if(!dev->chunkBits){ -+ dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); -+ dev->chunkBitsAlt = 1; - } -- -+ else -+ dev->chunkBitsAlt = 0; -+ - if (dev->blockInfo && dev->chunkBits) { - memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo)); - memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks); -@@ -2519,18 +1974,17 @@ - - static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) - { -- if(dev->blockInfoAlt && dev->blockInfo) -+ if(dev->blockInfoAlt) - YFREE_ALT(dev->blockInfo); -- else if(dev->blockInfo) -+ else - YFREE(dev->blockInfo); -- - dev->blockInfoAlt = 0; - - dev->blockInfo = NULL; -- -- if(dev->chunkBitsAlt && dev->chunkBits) -+ -+ if(dev->chunkBitsAlt) - YFREE_ALT(dev->chunkBits); -- else if(dev->chunkBits) -+ else - YFREE(dev->chunkBits); - dev->chunkBitsAlt = 0; - dev->chunkBits = NULL; -@@ -2587,18 +2041,17 @@ - int i; - int iterations; - int dirtiest = -1; -- int pagesInUse = 0; -+ int pagesInUse; - int prioritised=0; - yaffs_BlockInfo *bi; -+ static int nonAggressiveSkip = 0; - 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 +2063,7 @@ - } - } - } -- -+ - if(!pendingPrioritisedExist) /* None found, so we can clear this */ - dev->hasPendingPrioritisedGCs = 0; - } -@@ -2621,9 +2074,9 @@ - * block has only a few pages in use. - */ - -- dev->nonAggressiveSkip--; -+ nonAggressiveSkip--; - -- if (!aggressive && (dev->nonAggressiveSkip > 0)) { -+ if (!aggressive && (nonAggressiveSkip > 0)) { - return -1; - } - -@@ -2662,7 +2115,7 @@ - dirtiest = b; - pagesInUse = 0; - } -- else -+ else - #endif - - if (bi->blockState == YAFFS_BLOCK_STATE_FULL && -@@ -2684,7 +2137,7 @@ - dev->oldestDirtySequence = 0; - - if (dirtiest > 0) { -- dev->nonAggressiveSkip = 4; -+ nonAggressiveSkip = 4; - } - - return dirtiest; -@@ -2699,11 +2152,11 @@ - /* 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,8 +2169,7 @@ - } - } - -- if (erasedOk && -- ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) { -+ if (erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE)) { - int i; - for (i = 0; i < dev->nChunksPerBlock; i++) { - if (!yaffs_CheckChunkErased -@@ -2767,7 +2219,7 @@ - - return -1; - } -- -+ - /* Find an empty block. */ - - for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -@@ -2808,13 +2260,13 @@ - int reservedChunks; - int reservedBlocks = dev->nReservedBlocks; - int checkpointBlocks; -- -+ - checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; - if(checkpointBlocks < 0) - checkpointBlocks = 0; -- -+ - reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock); -- -+ - return (dev->nFreeChunks > reservedChunks); - } - -@@ -2861,10 +2313,10 @@ - - if(blockUsedPtr) - *blockUsedPtr = bi; -- -+ - return retVal; - } -- -+ - T(YAFFS_TRACE_ERROR, - (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); - -@@ -2895,7 +2347,6 @@ - int cleanups = 0; - int i; - int isCheckpointBlock; -- int matchingChunk; - - int chunksBefore = yaffs_GetErasedChunks(dev); - int chunksAfter; -@@ -2907,7 +2358,7 @@ - yaffs_Object *object; - - isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT); -- -+ - bi->blockState = YAFFS_BLOCK_STATE_COLLECTING; - - T(YAFFS_TRACE_TRACING, -@@ -2936,8 +2387,6 @@ - - __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); -@@ -2963,34 +2412,18 @@ - chunkInBlock, tags.objectId, tags.chunkId, - tags.byteCount)); - -- if(object && !yaffs_SkipVerification(dev)){ -- if(tags.chunkId == 0) -- matchingChunk = object->chunkId; -- 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) { - T(YAFFS_TRACE_ERROR, - (TSTR -- ("page %d in gc has no object: %d %d %d " -- TENDSTR), oldChunk, -- tags.objectId, tags.chunkId, tags.byteCount)); -+ ("page %d in gc has no object " -+ TENDSTR), oldChunk)); - } - - if (object && object->deleted - && tags.chunkId != 0) { - /* Data chunk in a 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. - */ - -@@ -3040,8 +2473,6 @@ - oh->shadowsObject = -1; - tags.extraShadows = 0; - tags.extraIsShrinkHeader = 0; -- -- yaffs_VerifyObjectHeader(object,oh,&tags,1); - } - - newChunk = -@@ -3098,8 +2529,6 @@ - - } - -- yaffs_VerifyCollectedBlock(dev,bi,block); -- - if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) { - T(YAFFS_TRACE_GC, - (TSTR -@@ -3127,26 +2556,26 @@ - 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); - if(checkpointBlockAdjust < 0) - checkpointBlockAdjust = 0; - -- if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust + 2)) { -+ if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) { - /* We need a block soon...*/ - aggressive = 1; - } else { -@@ -3326,11 +2755,11 @@ - 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 +2783,7 @@ - return YAFFS_OK; - } - -- tn = yaffs_AddOrFindLevel0Tnode(dev, -+ tn = yaffs_AddOrFindLevel0Tnode(dev, - &in->variant.fileVariant, - chunkInInode, - NULL); -@@ -3366,7 +2795,7 @@ - - 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. - * -@@ -3407,7 +2836,7 @@ - - } - -- /* 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 - */ - -@@ -3418,7 +2847,7 @@ - (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 +2888,7 @@ - (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; - } - -@@ -3475,17 +2904,10 @@ - if (chunkId <= 0) - return; - -- - dev->nDeletions++; - block = chunkId / dev->nChunksPerBlock; - page = chunkId % dev->nChunksPerBlock; - -- -- if(!yaffs_CheckChunkBit(dev,block,page)) -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Deleting invalid chunk %d"TENDSTR), -- chunkId)); -- - bi = yaffs_GetBlockInfo(dev, block); - - T(YAFFS_TRACE_DELETION, -@@ -3596,19 +3018,15 @@ - - int newChunkId; - yaffs_ExtendedTags newTags; -- yaffs_ExtendedTags oldTags; - - __u8 *buffer = NULL; - YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1]; - - yaffs_ObjectHeader *oh = NULL; - -- yaffs_strcpy(oldName,"silly old name"); -- - if (!in->fake || force) { - - yaffs_CheckGarbageCollection(dev); -- yaffs_CheckObjectDetailsLoaded(in); - - buffer = yaffs_GetTempBuffer(in->myDev, __LINE__); - oh = (yaffs_ObjectHeader *) buffer; -@@ -3617,10 +3035,7 @@ - - if (prevChunkId >= 0) { - result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId, -- buffer, &oldTags); -- -- yaffs_VerifyObjectHeader(in,oh,&oldTags,0); -- -+ buffer, NULL); - memcpy(oldName, oh->name, sizeof(oh->name)); - } - -@@ -3654,7 +3069,7 @@ - if (name && *name) { - memset(oh->name, 0, sizeof(oh->name)); - yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH); -- } else if (prevChunkId>=0) { -+ } else if (prevChunkId) { - memcpy(oh->name, oldName, sizeof(oh->name)); - } else { - memset(oh->name, 0, sizeof(oh->name)); -@@ -3708,8 +3123,6 @@ - newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0; - newTags.extraObjectType = in->variantType; - -- yaffs_VerifyObjectHeader(in,oh,&newTags,1); -- - /* Create new chunk in NAND */ - newChunkId = - yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, -@@ -3748,11 +3161,11 @@ - - /*------------------------ 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 +3178,14 @@ - 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 +3251,7 @@ - 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,18 +3261,18 @@ - 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. - */ -@@ -3871,7 +3284,7 @@ - - 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]; - } - -@@ -4032,14 +3445,11 @@ - 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 +3458,9 @@ - { - 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 +3469,20 @@ - 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 +3492,7 @@ - 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 +3508,20 @@ - __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 +3536,28 @@ - __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; - } - -@@ -4158,7 +3568,7 @@ - cp->objectId = obj->objectId; - cp->parentId = (obj->parent) ? obj->parent->objectId : 0; - cp->chunkId = obj->chunkId; -- cp->variantType = obj->variantType; -+ cp->variantType = obj->variantType; - cp->deleted = obj->deleted; - cp->softDeleted = obj->softDeleted; - cp->unlinked = obj->unlinked; -@@ -4167,7 +3577,7 @@ - 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 +3588,9 @@ - { - - yaffs_Object *parent; -- -+ - obj->objectId = cp->objectId; -- -+ - if(cp->parentId) - parent = yaffs_FindOrCreateObjectByNumber( - obj->myDev, -@@ -4188,12 +3598,12 @@ - YAFFS_OBJECT_TYPE_DIRECTORY); - else - parent = NULL; -- -+ - if(parent) - yaffs_AddObjectToDirectory(parent, obj); -- -+ - obj->chunkId = cp->chunkId; -- obj->variantType = cp->variantType; -+ obj->variantType = cp->variantType; - obj->deleted = cp->deleted; - obj->softDeleted = cp->softDeleted; - obj->unlinked = cp->unlinked; -@@ -4202,12 +3612,12 @@ - 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) - obj->lazyLoaded = 1; - } -@@ -4250,17 +3660,17 @@ - { - __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; - } - -@@ -4271,15 +3681,12 @@ - yaffs_Device *dev = obj->myDev; - yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant; - yaffs_Tnode *tn; -- int nread = 0; -- -+ - 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) -@@ -4287,27 +3694,22 @@ - (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); - 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) - { -@@ -4317,11 +3719,11 @@ - int ok = 1; - struct list_head *lh; - -- -+ - /* 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) { -@@ -4333,9 +3735,9 @@ - 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)); -- -+ - ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -- -+ - if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){ - ok = yaffs_WriteCheckpointTnodes(obj); - } -@@ -4343,14 +3745,14 @@ - } - } - } -- -+ - /* 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,22 +3763,20 @@ - 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)) { -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("struct size %d instead of %d ok %d"TENDSTR), -- cp.structType,sizeof(cp),ok)); -+ /* printf("structure parsing failed\n"); */ - 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)); -- -+ - if(ok && cp.objectId == ~0) - done = 1; - else if(ok){ - obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d obj addr %x" TENDSTR), -+ cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); - if(obj) { - yaffs_CheckpointObjectToObject(obj,&cp); - if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { -@@ -4387,93 +3787,39 @@ - hardList; - hardList = obj; - } -- -+ - } - } - } -- -+ - if(ok) - yaffs_HardlinkFixup(dev,hardList); -- -+ - return ok ? 1 : 0; - } - --static int yaffs_WriteCheckpointSum(yaffs_Device *dev) --{ -- __u32 checkpointSum; -- int ok; -- -- yaffs_GetCheckpointSum(dev,&checkpointSum); -- -- ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum)); -- -- if(!ok) -- return 0; -- -- return 1; --} -- --static int yaffs_ReadCheckpointSum(yaffs_Device *dev) --{ -- __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; --} -- -- - static int yaffs_WriteCheckpointData(yaffs_Device *dev) - { - -- int ok = 1; -- -- if(dev->skipCheckpointWrite || !dev->isYaffs2){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR))); -- ok = 0; -- } -- -+ int ok; -+ -+ ok = yaffs_CheckpointOpen(dev,1); -+ - if(ok) -- ok = yaffs_CheckpointOpen(dev,1); -- -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); - ok = yaffs_WriteCheckpointValidityMarker(dev,1); -- } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint device" TENDSTR))); -+ if(ok) - ok = yaffs_WriteCheckpointDevice(dev); -- } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint objects" TENDSTR))); -+ if(ok) - ok = yaffs_WriteCheckpointObjects(dev); -- } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -+ if(ok) - 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; -@@ -4481,44 +3827,27 @@ - - 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; -- } -- -+ int ok; -+ -+ ok = yaffs_CheckpointOpen(dev,0); /* open for read */ -+ - if(ok) -- ok = yaffs_CheckpointOpen(dev,0); /* open for read */ -- -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); - ok = yaffs_ReadCheckpointValidityMarker(dev,1); -- } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint device" TENDSTR))); -+ if(ok) - ok = yaffs_ReadCheckpointDevice(dev); -- } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR))); -+ if(ok) - ok = yaffs_ReadCheckpointObjects(dev); -- } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -+ if(ok) - ok = yaffs_ReadCheckpointValidityMarker(dev,0); -- } -+ - -- if(ok){ -- ok = yaffs_ReadCheckpointSum(dev); -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok)); -- } - - if(!yaffs_CheckpointClose(dev)) - ok = 0; - - if(ok) - dev->isCheckpointed = 1; -- else -+ else - dev->isCheckpointed = 0; - - return ok ? 1 : 0; -@@ -4527,7 +3856,7 @@ - - static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) - { -- if(dev->isCheckpointed || -+ if(dev->isCheckpointed || - dev->blocksInCheckpoint > 0){ - dev->isCheckpointed = 0; - yaffs_CheckpointInvalidateStream(dev); -@@ -4539,19 +3868,13 @@ - - int yaffs_CheckpointSave(yaffs_Device *dev) - { -- -+ yaffs_ReportOddballBlocks(dev); - T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); - -- yaffs_VerifyObjects(dev); -- yaffs_VerifyBlocks(dev); -- yaffs_VerifyFreeChunks(dev); -- -- if(!dev->isCheckpointed) { -- yaffs_InvalidateCheckpoint(dev); -+ if(!dev->isCheckpointed) - yaffs_WriteCheckpointData(dev); -- } -- -- T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ -+ T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); - - return dev->isCheckpointed; - } -@@ -4560,17 +3883,13 @@ - { - int retval; - T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -- -+ - retval = yaffs_ReadCheckpointData(dev); - -- if(dev->isCheckpointed){ -- yaffs_VerifyObjects(dev); -- yaffs_VerifyBlocks(dev); -- yaffs_VerifyFreeChunks(dev); -- } -- - T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -- -+ -+ yaffs_ReportOddballBlocks(dev); -+ - return retval; - } - -@@ -4606,7 +3925,7 @@ - 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; -@@ -4763,7 +4082,7 @@ - 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,12 +4095,12 @@ - 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; - } - -@@ -4945,9 +4264,9 @@ - int oldFileSize = in->variant.fileVariant.fileSize; - int newSizeOfPartialChunk; - int newFullChunks; -- -+ - yaffs_Device *dev = in->myDev; -- -+ - yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk); - - yaffs_FlushFilesChunkCache(in); -@@ -4969,7 +4288,7 @@ - - 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,8 +4312,8 @@ - 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. -@@ -5058,7 +4377,7 @@ - - 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, NULL, 0, 0); - - } - -@@ -5096,7 +4415,7 @@ - if (immediateDeletion) { - retVal = - yaffs_ChangeObjectName(in, in->myDev->deletedDir, -- "deleted", 0, 0); -+ NULL, 0, 0); - T(YAFFS_TRACE_TRACING, - (TSTR("yaffs: immediate deletion of file %d" TENDSTR), - in->objectId)); -@@ -5109,7 +4428,7 @@ - } else { - retVal = - yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, -- "unlinked", 0, 0); -+ NULL, 0, 0); - } - - } -@@ -5313,7 +4632,7 @@ - { - yaffs_Object *hl; - yaffs_Object *in; -- -+ - while (hardList) { - hl = hardList; - hardList = (yaffs_Object *) (hardList->hardLinks.next); -@@ -5370,6 +4689,7 @@ - int deleted; - yaffs_BlockState state; - yaffs_Object *hardList = NULL; -+ yaffs_Object *hl; - yaffs_BlockInfo *bi; - int sequenceNumber; - yaffs_ObjectHeader *oh; -@@ -5377,9 +4697,6 @@ - yaffs_Object *parent; - int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; - -- int alloc_failed = 0; -- -- - __u8 *chunkData; - - yaffs_BlockIndex *blockIndex = NULL; -@@ -5389,9 +4706,9 @@ - (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)); -@@ -5402,8 +4719,6 @@ - - if (dev->isYaffs2) { - blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); -- if(!blockIndex) -- return YAFFS_FAIL; - } - - /* Scan all the blocks to determine their state */ -@@ -5485,7 +4800,7 @@ - } - - /* For each block.... */ -- for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator; -+ for (blockIterator = startIterator; blockIterator <= endIterator; - blockIterator++) { - - if (dev->isYaffs2) { -@@ -5501,7 +4816,7 @@ - deleted = 0; - - /* For each chunk in each block that needs scanning....*/ -- for (c = 0; !alloc_failed && c < dev->nChunksPerBlock && -+ for (c = 0; c < dev->nChunksPerBlock && - state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) { - /* Read the tags and decide what to do */ - chunk = blk * dev->nChunksPerBlock + c; -@@ -5520,7 +4835,7 @@ - /*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,9 +4852,9 @@ - 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 - */ -@@ -5569,20 +4884,12 @@ - /* PutChunkIntoFile checks for a clash (two data chunks with - * the same chunkId). - */ -- -- if(!in) -- alloc_failed = 1; -- -- if(in){ -- if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1)) -- alloc_failed = 1; -- } -- -+ yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, -+ 1); - endpos = - (tags.chunkId - 1) * dev->nDataBytesPerChunk + - tags.byteCount; -- if (in && -- in->variantType == YAFFS_OBJECT_TYPE_FILE -+ if (in->variantType == YAFFS_OBJECT_TYPE_FILE - && in->variant.fileVariant.scannedFileSize < - endpos) { - in->variant.fileVariant. -@@ -5613,7 +4920,7 @@ - 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. - */ - -@@ -5627,17 +4934,14 @@ - objectId, - oh->type); - -- if(!in) -- alloc_failed = 1; -- -- if (in && oh->shadowsObject > 0) { -+ if (oh->shadowsObject > 0) { - yaffs_HandleShadowedObject(dev, - oh-> - shadowsObject, - 0); - } - -- if (in && in->valid) { -+ if (in->valid) { - /* We have already filled this one. We have a duplicate and need to resolve it. */ - - unsigned existingSerial = in->serial; -@@ -5658,7 +4962,7 @@ - } - } - -- if (in && !in->valid && -+ if (!in->valid && - (tags.objectId == YAFFS_OBJECTID_ROOT || - tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) { - /* We only load some info, don't fiddle with directory structure */ -@@ -5683,7 +4987,7 @@ - #endif - in->chunkId = chunk; - -- } else if (in && !in->valid) { -+ } else if (!in->valid) { - /* we need to load this info */ - - in->valid = 1; -@@ -5752,11 +5056,11 @@ - * 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: -@@ -5791,11 +5095,10 @@ - case YAFFS_OBJECT_TYPE_SPECIAL: - /* Do nothing */ - break; -- case YAFFS_OBJECT_TYPE_SYMLINK: -- in->variant.symLinkVariant.alias = -+ case YAFFS_OBJECT_TYPE_SYMLINK: -+ in->variant.symLinkVariant. -+ alias = - yaffs_CloneString(oh->alias); -- if(!in->variant.symLinkVariant.alias) -- alloc_failed = 1; - break; - } - -@@ -5826,11 +5129,11 @@ - 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. - */ - -@@ -5857,13 +5160,8 @@ - - yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); - -- if(alloc_failed){ -- return YAFFS_FAIL; -- } -- - T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR))); - -- - return YAFFS_OK; - } - -@@ -5874,23 +5172,19 @@ - yaffs_Device *dev = in->myDev; - yaffs_ExtendedTags tags; - int result; -- int alloc_failed = 0; -- -- if(!in) -- return; -- -+ - #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){ - in->lazyLoaded = 0; - chunkData = yaffs_GetTempBuffer(dev, __LINE__); - - result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags); -- oh = (yaffs_ObjectHeader *) chunkData; -+ oh = (yaffs_ObjectHeader *) chunkData; - - in->yst_mode = oh->yst_mode; - #ifdef CONFIG_YAFFS_WINCE -@@ -5907,17 +5201,14 @@ - 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){ -+ -+ 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__); - } - } -@@ -5945,13 +5236,12 @@ - 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 +5261,18 @@ - 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 +5289,15 @@ - - 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++; -- -+ /* todo .. fix free space ? */ -+ - } else if (state == YAFFS_BLOCK_STATE_DEAD) { - T(YAFFS_TRACE_BAD_BLOCKS, - (TSTR("block %d is bad" TENDSTR), blk)); -@@ -6053,12 +5341,14 @@ - - /* Sort the blocks */ - #ifndef CONFIG_YAFFS_USE_OWN_SORT -- yaffs_qsort(blockIndex, nBlocksToScan, -- sizeof(yaffs_BlockIndex), ybicmp); -+ { -+ /* Use qsort now. */ -+ qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); -+ } - #else - { - /* Dungy old bubble sort... */ -- -+ - yaffs_BlockIndex temp; - int i; - int j; -@@ -6084,7 +5374,7 @@ - (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan)); - - /* For each block.... backwards */ -- for (blockIterator = endIterator; !alloc_failed && blockIterator >= startIterator; -+ for (blockIterator = endIterator; blockIterator >= startIterator; - blockIterator--) { - /* Cooperative multitasking! This loop can run for so - long that watchdog timers expire. */ -@@ -6094,22 +5384,18 @@ - 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; -- !alloc_failed && c >= 0 && -+ for (c = dev->nChunksPerBlock - 1; 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 +5409,14 @@ - * 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 +5426,7 @@ - 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 +5435,34 @@ - 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->gcPrioritise = 1; -- -+ - T(YAFFS_TRACE_ALWAYS, - (TSTR("Partially written block %d being set for retirement" TENDSTR), - blk)); - } - - } -- -+ - } - - 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; - - -@@ -6187,29 +5473,21 @@ - tags. - objectId, - YAFFS_OBJECT_TYPE_FILE); -- if(!in){ -- /* Out of memory */ -- alloc_failed = 1; -- } -- -- if (in && -- in->variantType == YAFFS_OBJECT_TYPE_FILE -+ if (in->variantType == YAFFS_OBJECT_TYPE_FILE - && chunkBase < - in->variant.fileVariant.shrinkSize) { - /* This has not been invalidated by a resize */ -- if(!yaffs_PutChunkIntoFile(in, tags.chunkId, -- chunk, -1)){ -- alloc_failed = 1; -- } -+ yaffs_PutChunkIntoFile(in, tags.chunkId, -+ chunk, -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) { -@@ -6221,7 +5499,7 @@ - scannedFileSize; - } - -- } else if(in) { -+ } else { - /* This chunk has been invalidated by a resize, so delete */ - yaffs_DeleteChunk(dev, chunk, 1, __LINE__); - -@@ -6255,7 +5533,7 @@ - ) { - - /* 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. - */ - -@@ -6283,12 +5561,12 @@ - - 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)) -@@ -6339,7 +5617,7 @@ - YAFFS_OBJECTID_LOSTNFOUND)) { - /* We only load some info, don't fiddle with directory structure */ - in->valid = 1; -- -+ - if(oh) { - in->variantType = oh->type; - -@@ -6358,13 +5636,13 @@ - 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; - - } else if (!in->valid) { -@@ -6372,7 +5650,7 @@ - - in->valid = 1; - in->chunkId = chunk; -- -+ - if(oh) { - in->variantType = oh->type; - -@@ -6393,12 +5671,12 @@ - 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 = -@@ -6466,11 +5744,11 @@ - * 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 +5757,7 @@ - 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; -@@ -6509,21 +5787,16 @@ - /* Do nothing */ - break; - case YAFFS_OBJECT_TYPE_SYMLINK: -- if(oh){ -+ if(oh) - in->variant.symLinkVariant.alias = - yaffs_CloneString(oh-> - alias); -- if(!in->variant.symLinkVariant.alias) -- alloc_failed = 1; -- } - break; - } - - } -- - } -- -- } /* End of scanning for each chunk */ -+ } - - if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { - /* If we got this far while scanning, then the block is fully allocated. */ -@@ -6541,19 +5814,19 @@ - - } - -- 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); -- -- -+ -+ - /* - * Sort out state of unlinked and deleted objects. - */ -@@ -6587,10 +5860,6 @@ - - yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); - -- if(alloc_failed){ -- return YAFFS_FAIL; -- } -- - T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); - - return YAFFS_OK; -@@ -6601,10 +5870,10 @@ - static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) - { - yaffs_Device *dev = obj->myDev; -- -+ - if(dev && dev->removeObjectCallback) - dev->removeObjectCallback(obj); -- -+ - list_del_init(&obj->siblings); - obj->parent = NULL; - } -@@ -6682,7 +5951,7 @@ - list_for_each(i, &directory->variant.directoryVariant.children) { - if (i) { - l = list_entry(i, yaffs_Object, siblings); -- -+ - yaffs_CheckObjectDetailsLoaded(l); - - /* Special case for lost-n-found */ -@@ -6690,14 +5959,14 @@ - if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) { - return l; - } -- } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) -+ } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) - { - /* LostnFound cunk called Objxxx - * Do a real check - */ - yaffs_GetObjectName(l, buffer, - YAFFS_MAX_NAME_LENGTH); -- if (yaffs_strncmp(name, buffer,YAFFS_MAX_NAME_LENGTH) == 0) { -+ if (yaffs_strcmp(name, buffer) == 0) { - return l; - } - -@@ -6753,7 +6022,6 @@ - if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { - /* We want the object id of the equivalent object, not this one */ - obj = obj->variant.hardLinkVariant.equivalentObject; -- yaffs_CheckObjectDetailsLoaded(obj); - } - return obj; - -@@ -6762,7 +6030,7 @@ - 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) { -@@ -6991,16 +6259,15 @@ - } - - --static int yaffs_CreateInitialDirectories(yaffs_Device *dev) -+static void 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,18 +6277,11 @@ - 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; -+ yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir); - } - - int yaffs_GutsInitialise(yaffs_Device * dev) - { -- int init_failed = 0; - unsigned x; - int bits; - -@@ -7049,12 +6309,12 @@ - - /* 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->isYaffs2 && dev->nDataBytesPerChunk < 1024) || -+ (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || -+ 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, -@@ -7100,9 +6360,9 @@ - - - /* 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); -@@ -7121,7 +6381,7 @@ - dev->chunkShift = 0; - dev->chunkMask = 0; - } -- -+ - - /* - * Calculate chunkGroupBits. -@@ -7129,9 +6389,9 @@ - */ - - 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 +6404,20 @@ - } - else - dev->tnodeWidth = 16; -- -+ - dev->tnodeMask = (1<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; - -@@ -7193,111 +6453,71 @@ - dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */ - - /* 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; -+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { -+ dev->tempBuffer[i].line = 0; /* not in use */ -+ dev->tempBuffer[i].buffer = -+ YMALLOC_DMA(dev->nDataBytesPerChunk); -+ } -+ } -+ -+ if (dev->nShortOpCaches > 0) { - int i; -- __u8 *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(dev->nShortOpCaches * sizeof(yaffs_ChunkCache)); - -- if(dev->srCache) -- memset(dev->srCache,0,srCacheBytes); -- -- for (i = 0; i < dev->nShortOpCaches && buf; i++) { -+ for (i = 0; i < dev->nShortOpCaches; 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 = YMALLOC_DMA(dev->nDataBytesPerChunk); - } -- if(!buf) -- init_failed = 1; -- - dev->srLastUse = 0; - } - - dev->cacheHits = 0; -- -- if(!init_failed){ -- dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); -- if(!dev->gcCleanupList) -- init_failed = 1; -- } -+ -+ dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); - - if (dev->isYaffs2) { - dev->useHeaderFileSize = 1; - } -- if(!init_failed && !yaffs_InitialiseBlocks(dev)) -- init_failed = 1; - -+ yaffs_InitialiseBlocks(dev); - yaffs_InitialiseTnodes(dev); - yaffs_InitialiseObjects(dev); - -- if(!init_failed && !yaffs_CreateInitialDirectories(dev)) -- init_failed = 1; -- -- -- if(!init_failed){ -- /* Now scan the flash. */ -- if (dev->isYaffs2) { -- if(yaffs_CheckpointRestore(dev)) { -- T(YAFFS_TRACE_ALWAYS, -- (TSTR("yaffs: restored from checkpoint" TENDSTR))); -- } else { -- -- /* 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; -- dev->allocationPage = -1; -- dev->nDeletedFiles = 0; -- dev->nUnlinkedFiles = 0; -- dev->nBackgroundDeletions = 0; -- dev->oldestDirtySequence = 0; -+ yaffs_CreateInitialDirectories(dev); - -- if(!init_failed && !yaffs_InitialiseBlocks(dev)) -- init_failed = 1; - -- yaffs_InitialiseTnodes(dev); -- yaffs_InitialiseObjects(dev); -- -- if(!init_failed && !yaffs_CreateInitialDirectories(dev)) -- init_failed = 1; -- -- if(!init_failed && !yaffs_ScanBackwards(dev)) -- init_failed = 1; -- } -- }else -- if(!yaffs_Scan(dev)) -- init_failed = 1; -- } -+ /* Now scan the flash. */ -+ if (dev->isYaffs2) { -+ if(yaffs_CheckpointRestore(dev)) { -+ T(YAFFS_TRACE_ALWAYS, -+ (TSTR("yaffs: restored from checkpoint" TENDSTR))); -+ } else { - -- if(init_failed){ -- /* Clean up the mess */ -- T(YAFFS_TRACE_TRACING, -- (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR))); -+ /* Clean up the mess caused by an aborted checkpoint load -+ * and scan backwards. -+ */ -+ yaffs_DeinitialiseBlocks(dev); -+ yaffs_DeinitialiseTnodes(dev); -+ yaffs_DeinitialiseObjects(dev); -+ yaffs_InitialiseBlocks(dev); -+ yaffs_InitialiseTnodes(dev); -+ yaffs_InitialiseObjects(dev); -+ yaffs_CreateInitialDirectories(dev); - -- yaffs_Deinitialise(dev); -- return YAFFS_FAIL; -- } -+ yaffs_ScanBackwards(dev); -+ } -+ }else -+ yaffs_Scan(dev); - - /* Zero out stats */ - dev->nPageReads = 0; -@@ -7309,9 +6529,6 @@ - dev->nRetiredBlocks = 0; - - yaffs_VerifyFreeChunks(dev); -- yaffs_VerifyBlocks(dev); -- -- - T(YAFFS_TRACE_TRACING, - (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR))); - return YAFFS_OK; -@@ -7326,17 +6543,13 @@ - yaffs_DeinitialiseBlocks(dev); - yaffs_DeinitialiseTnodes(dev); - yaffs_DeinitialiseObjects(dev); -- if (dev->nShortOpCaches > 0 && -- dev->srCache) { -+ if (dev->nShortOpCaches > 0) { - - for (i = 0; i < dev->nShortOpCaches; i++) { -- if(dev->srCache[i].data) -- YFREE(dev->srCache[i].data); -- dev->srCache[i].data = NULL; -+ YFREE(dev->srCache[i].data); - } - - YFREE(dev->srCache); -- dev->srCache = NULL; - } - - YFREE(dev->gcCleanupList); -@@ -7394,7 +6607,7 @@ - #endif - - nFree += dev->nDeletedFiles; -- -+ - /* Now count the number of dirty chunks in the cache and subtract those */ - - { -@@ -7408,12 +6621,12 @@ - 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; - if(blocksForCheckpoint < 0) - blocksForCheckpoint = 0; -- -+ - nFree -= (blocksForCheckpoint * dev->nChunksPerBlock); - - if (nFree < 0) -@@ -7427,15 +6640,9 @@ - - static void yaffs_VerifyFreeChunks(yaffs_Device * dev) - { -- int counted; -- int difference; -- -- if(yaffs_SkipVerification(dev)) -- return; -- -- counted = yaffs_CountFreeChunks(dev); -+ int counted = yaffs_CountFreeChunks(dev); - -- difference = dev->nFreeChunks - counted; -+ int difference = dev->nFreeChunks - counted; - - if (difference) { - T(YAFFS_TRACE_ALWAYS, -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_guts.h linux-2.6.24.7.new/fs/yaffs2/yaffs_guts.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_guts.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_guts.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 - -@@ -63,7 +63,9 @@ - - #define YAFFS_OBJECT_SPACE 0x40000 - --#define YAFFS_CHECKPOINT_VERSION 3 -+#define YAFFS_NCHECKPOINT_OBJECTS 5000 -+ -+#define YAFFS_CHECKPOINT_VERSION 2 - - #ifdef CONFIG_YAFFS_UNICODE - #define YAFFS_MAX_NAME_LENGTH 127 -@@ -92,17 +94,11 @@ - - #define YAFFS_N_TEMP_BUFFERS 4 - --/* 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. -- * Default to something in the order of 5 to 10 blocks worth of chunks. -- */ --#define YAFFS_WR_ATTEMPTS (5*64) -- - /* Sequence numbers are used in YAFFS2 to determine block allocation order. - * 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 -@@ -166,8 +162,6 @@ - YAFFS_OBJECT_TYPE_SPECIAL - } yaffs_ObjectType; - --#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL -- - typedef struct { - - unsigned validMarker0; -@@ -178,7 +172,7 @@ - - /* 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,35 +238,32 @@ - /* 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; - --#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1) -- -- - typedef struct { - - int softDeletions:10; /* number of soft deleted pages */ -@@ -281,7 +272,7 @@ - __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 bank 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 */ - -@@ -408,7 +399,7 @@ - __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). - */ -@@ -430,11 +421,11 @@ - - /* directory structure stuff */ - /* also used for linking up the free list */ -- struct yaffs_ObjectStruct *parent; -+ struct yaffs_ObjectStruct *parent; - struct list_head siblings; - - /* Where's my object header in NAND? */ -- int chunkId; -+ int chunkId; - - int nDataChunks; /* Number of data chunks attached to the file. */ - -@@ -490,26 +481,26 @@ - } 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; -- -+ - 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; -@@ -539,14 +530,17 @@ - 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 partitioned checkpointing mechanism */ -+ int checkpointStartBlock; -+ int checkpointEndBlock; -+ - /* 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 nShortOpCaches; /* If <= 0, then short op caching is disabled, else -@@ -561,7 +555,7 @@ - * 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, -@@ -587,57 +581,53 @@ - #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 */ -- -+ - - /* End of stuff that must be set before initialisation. */ - -- /* Checkpoint control. Can be set before or after initialisation */ -- __u8 skipCheckpointRead; -- __u8 skipCheckpointWrite; -- - /* Runtime parameters. Set up by YAFFS. */ - - __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; -- -+ - - #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 +636,7 @@ - int internalEndBlock; - int blockOffset; - int chunkOffset; -- -+ - - /* Runtime checkpointing stuff */ - int checkpointPageSequence; /* running sequence number of checkpoint pages */ -@@ -660,15 +650,13 @@ - int checkpointNextBlock; - int *checkpointBlockList; - int checkpointMaxBlocks; -- __u32 checkpointSum; -- __u32 checkpointXor; -- -+ - /* 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. - */ - -@@ -698,7 +686,6 @@ - int currentDirtyChecker; /* Used to find current dirtiest block */ - - __u32 *gcCleanupList; /* objects to delete at the end of a GC. */ -- int nonAggressiveSkip; /* GC state/mode */ - - /* Statistcs */ - int nPageWrites; -@@ -716,7 +703,7 @@ - int tagsEccUnfixed; - int nDeletions; - int nUnmarkedDeletions; -- -+ - int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */ - - /* Special directories */ -@@ -727,7 +714,7 @@ - * __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; - -@@ -768,7 +755,7 @@ - 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. - */ -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.c 2009-04-21 15:01:02.000000000 +0200 -@@ -12,13 +12,10 @@ - */ - - 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.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; - - #include "yportenv.h" -- -- - #include "yaffs_mtdif.h" -- - #include "linux/mtd/mtd.h" - #include "linux/types.h" - #include "linux/time.h" -@@ -54,6 +51,7 @@ - static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob) - { - struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare; -+ - spare->tagByte0 = oob[0]; - spare->tagByte1 = oob[1]; - spare->tagByte2 = oob[2]; -@@ -68,6 +66,11 @@ - spare->ecc2[0] = spare->ecc2[1] = spare->ecc2[2] = 0xff; - - nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */ -+#if 0 -+ char i; -+ for (i=0;i<8;i++) -+ printk("oob %d :%x",i,oob[i]); -+#endif - } - #endif - -@@ -78,10 +81,11 @@ - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - struct mtd_oob_ops ops; - #endif -- size_t dummy; -+ size_mtd_t dummy; - int retval = 0; - -- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - __u8 spareAsBytes[8]; /* OOB */ - -@@ -142,10 +146,11 @@ - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - struct mtd_oob_ops ops; - #endif -- size_t dummy; -+ size_mtd_t dummy; - int retval = 0; - -- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - __u8 spareAsBytes[8]; /* OOB */ - -@@ -164,7 +169,7 @@ - ops.datbuf = data; - ops.ooboffs = 0; - ops.oobbuf = spareAsBytes; -- retval = mtd->read_oob(mtd, addr, &ops); -+ retval = mtd->read_oob(mtd, addr, &ops); - if (dev->useNANDECC) - translate_oob2spare(spare, spareAsBytes); - } -@@ -172,7 +177,7 @@ - __u8 *spareAsBytes = (__u8 *) spare; - - if (data && spare) { -- if (dev->useNANDECC) { -+ if (dev->useNANDECC) { - /* Careful, this call adds 2 ints */ - /* to the end of the spare data. Calling function */ - /* should allocate enough memory for spare, */ -@@ -208,8 +213,8 @@ - int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -- __u32 addr = -- ((loff_t) blockNumber) * dev->nDataBytesPerChunk -+ __u64 addr = -+ ((loff_mtd_t) blockNumber) * dev->nDataBytesPerChunk - * dev->nChunksPerBlock; - struct erase_info ei; - int retval = 0; -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.h linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1-compat.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1-compat.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1-compat.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1-compat.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,434 +0,0 @@ --From ian@brightstareng.com Fri May 18 15:06:49 2007 --From ian@brightstareng.com Fri May 18 15:08:21 2007 --Received: from 206.173.66.57.ptr.us.xo.net ([206.173.66.57] helo=zebra.brightstareng.com) -- by apollo.linkchoose.co.uk with esmtp (Exim 4.60) -- (envelope-from ) -- id 1Hp380-00011e-T6 -- for david.goodenough@linkchoose.co.uk; Fri, 18 May 2007 15:08:21 +0100 --Received: from localhost (localhost.localdomain [127.0.0.1]) -- by zebra.brightstareng.com (Postfix) with ESMTP -- id 4819F28C004; Fri, 18 May 2007 10:07:49 -0400 (EDT) --Received: from zebra.brightstareng.com ([127.0.0.1]) -- by localhost (zebra [127.0.0.1]) (amavisd-new, port 10024) with ESMTP -- id 05328-06; Fri, 18 May 2007 10:07:16 -0400 (EDT) --Received: from pippin (unknown [192.168.1.25]) -- by zebra.brightstareng.com (Postfix) with ESMTP -- id 8BEF528C1BC; Fri, 18 May 2007 10:06:53 -0400 (EDT) --From: Ian McDonnell --To: David Goodenough --Subject: Re: something tested this time -- yaffs_mtdif1-compat.c --Date: Fri, 18 May 2007 10:06:49 -0400 --User-Agent: KMail/1.9.1 --References: <200705142207.06909.ian@brightstareng.com> <200705171131.53536.ian@brightstareng.com> <200705181334.32166.david.goodenough@linkchoose.co.uk> --In-Reply-To: <200705181334.32166.david.goodenough@linkchoose.co.uk> --Cc: Andrea Conti , -- Charles Manning --MIME-Version: 1.0 --Content-Type: Multipart/Mixed; -- boundary="Boundary-00=_5LbTGmt62YoutxM" --Message-Id: <200705181006.49860.ian@brightstareng.com> --X-Virus-Scanned: by amavisd-new at brightstareng.com --Status: R --X-Status: NT --X-KMail-EncryptionState: --X-KMail-SignatureState: --X-KMail-MDN-Sent: -- ----Boundary-00=_5LbTGmt62YoutxM --Content-Type: text/plain; -- charset="iso-8859-15" --Content-Transfer-Encoding: 7bit --Content-Disposition: inline -- --David, Andrea, -- --On Friday 18 May 2007 08:34, you wrote: --> Yea team. With this fix in place (I put it in the wrong place --> at first) I can now mount and ls the Yaffs partition without --> an error messages! -- --Good news! -- --Attached is a newer yaffs_mtdif1.c with a bandaid to help the --2.6.18 and 2.6.19 versions of MTD not trip on the oob read. --See the LINUX_VERSION_CODE conditional in --nandmtd1_ReadChunkWithTagsFromNAND. -- ---imcd -- ----Boundary-00=_5LbTGmt62YoutxM --Content-Type: text/x-csrc; -- charset="iso-8859-15"; -- name="yaffs_mtdif1.c" --Content-Transfer-Encoding: 7bit --Content-Disposition: attachment; -- filename="yaffs_mtdif1.c" -- --/* -- * YAFFS: Yet another FFS. A NAND-flash specific file system. -- * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND. -- * -- * Copyright (C) 2002 Aleph One Ltd. -- * for Toby Churchill Ltd and Brightstar Engineering -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --/* -- * This module provides the interface between yaffs_nand.c and the -- * MTD API. This version is used when the MTD interface supports the -- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, -- * and we have small-page NAND device. -- * -- * These functions are invoked via function pointers in yaffs_nand.c. -- * This replaces functionality provided by functions in yaffs_mtdif.c -- * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are -- * called in yaffs_mtdif.c when the function pointers are NULL. -- * We assume the MTD layer is performing ECC (useNANDECC is true). -- */ -- --#include "yportenv.h" --#include "yaffs_guts.h" --#include "yaffs_packedtags1.h" --#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC -- --#include "linux/kernel.h" --#include "linux/version.h" --#include "linux/types.h" --#include "linux/mtd/mtd.h" -- --/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- --const char *yaffs_mtdif1_c_version = "$Id$"; -- --#ifndef CONFIG_YAFFS_9BYTE_TAGS --# define YTAG1_SIZE 8 --#else --# define YTAG1_SIZE 9 --#endif -- --#if 0 --/* Use the following nand_ecclayout with MTD when using -- * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout. -- * If you have existing Yaffs images and the byte order differs from this, -- * adjust 'oobfree' to match your existing Yaffs data. -- * -- * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the -- * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to -- * the 9th byte. -- * -- * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 -- * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P -- * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus -- * byte and B is the small-page bad-block indicator byte. -- */ --static struct nand_ecclayout nand_oob_16 = { -- .eccbytes = 6, -- .eccpos = { 8, 9, 10, 13, 14, 15 }, -- .oobavail = 9, -- .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } --}; --#endif -- --/* Write a chunk (page) of data to NAND. -- * -- * Caller always provides ExtendedTags data which are converted to a more -- * compact (packed) form for storage in NAND. A mini-ECC runs over the -- * contents of the tags meta-data; used to valid the tags when read. -- * -- * - Pack ExtendedTags to PackedTags1 form -- * - Compute mini-ECC for PackedTags1 -- * - Write data and packed tags to NAND. -- * -- * Note: Due to the use of the PackedTags1 meta-data which does not include -- * a full sequence number (as found in the larger PackedTags2 form) it is -- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as -- * discarded and dirty. This is not ideal: newer NAND parts are supposed -- * to be written just once. When Yaffs performs this operation, this -- * function is called with a NULL data pointer -- calling MTD write_oob -- * without data is valid usage (2.6.17). -- * -- * Any underlying MTD error results in YAFFS_FAIL. -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, -- int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int chunkBytes = dev->nDataBytesPerChunk; -- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -- struct mtd_oob_ops ops; -- yaffs_PackedTags1 pt1; -- int retval; -- -- /* we assume that PackedTags1 and yaffs_Tags are compatible */ -- compile_time_assertion(sizeof(yaffs_PackedTags1) == 12); -- compile_time_assertion(sizeof(yaffs_Tags) == 8); -- -- yaffs_PackTags1(&pt1, etags); -- yaffs_CalcTagsECC((yaffs_Tags *)&pt1); -- -- /* When deleting a chunk, the upper layer provides only skeletal -- * etags, one with chunkDeleted set. However, we need to update the -- * tags, not erase them completely. So we use the NAND write property -- * that only zeroed-bits stick and set tag bytes to all-ones and -- * zero just the (not) deleted bit. -- */ --#ifndef CONFIG_YAFFS_9BYTE_TAGS -- if (etags->chunkDeleted) { -- memset(&pt1, 0xff, 8); -- /* clear delete status bit to indicate deleted */ -- pt1.deleted = 0; -- } --#else -- ((__u8 *)&pt1)[8] = 0xff; -- if (etags->chunkDeleted) { -- memset(&pt1, 0xff, 8); -- /* zero pageStatus byte to indicate deleted */ -- ((__u8 *)&pt1)[8] = 0; -- } --#endif -- -- memset(&ops, 0, sizeof(ops)); -- ops.mode = MTD_OOB_AUTO; -- ops.len = (data) ? chunkBytes : 0; -- ops.ooblen = YTAG1_SIZE; -- ops.datbuf = (__u8 *)data; -- ops.oobbuf = (__u8 *)&pt1; -- -- retval = mtd->write_oob(mtd, addr, &ops); -- if (retval) { -- yaffs_trace(YAFFS_TRACE_MTD, -- "write_oob failed, chunk %d, mtd error %d\n", -- chunkInNAND, retval); -- } -- return retval ? YAFFS_FAIL : YAFFS_OK; --} -- --/* Return with empty ExtendedTags but add eccResult. -- */ --static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) --{ -- if (etags) { -- memset(etags, 0, sizeof(*etags)); -- etags->eccResult = eccResult; -- } -- return retval; --} -- --/* Read a chunk (page) from NAND. -- * -- * Caller expects ExtendedTags data to be usable even on error; that is, -- * all members except eccResult and blockBad are zeroed. -- * -- * - Check ECC results for data (if applicable) -- * - Check for blank/erased block (return empty ExtendedTags if blank) -- * - Check the PackedTags1 mini-ECC (correct if necessary/possible) -- * - Convert PackedTags1 to ExtendedTags -- * - Update eccResult and blockBad members to refect state. -- * -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, -- int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int chunkBytes = dev->nDataBytesPerChunk; -- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -- int eccres = YAFFS_ECC_RESULT_NO_ERROR; -- struct mtd_oob_ops ops; -- yaffs_PackedTags1 pt1; -- int retval; -- int deleted; -- -- memset(&ops, 0, sizeof(ops)); -- ops.mode = MTD_OOB_AUTO; -- ops.len = (data) ? chunkBytes : 0; -- ops.ooblen = YTAG1_SIZE; -- ops.datbuf = data; -- ops.oobbuf = (__u8 *)&pt1; -- --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) -- /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; -- * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. -- */ -- ops.len = (ops.datbuf) ? ops.len : ops.ooblen; --#endif -- /* Read page and oob using MTD. -- * Check status and determine ECC result. -- */ -- retval = mtd->read_oob(mtd, addr, &ops); -- if (retval) { -- yaffs_trace(YAFFS_TRACE_MTD, -- "read_oob failed, chunk %d, mtd error %d\n", -- chunkInNAND, retval); -- } -- -- switch (retval) { -- case 0: -- /* no error */ -- break; -- -- case -EUCLEAN: -- /* MTD's ECC fixed the data */ -- eccres = YAFFS_ECC_RESULT_FIXED; -- dev->eccFixed++; -- break; -- -- case -EBADMSG: -- /* MTD's ECC could not fix the data */ -- dev->eccUnfixed++; -- /* fall into... */ -- default: -- rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); -- etags->blockBad = (mtd->block_isbad)(mtd, addr); -- return YAFFS_FAIL; -- } -- -- /* Check for a blank/erased chunk. -- */ -- if (yaffs_CheckFF((__u8 *)&pt1, 8)) { -- /* when blank, upper layers want eccResult to be <= NO_ERROR */ -- return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); -- } -- --#ifndef CONFIG_YAFFS_9BYTE_TAGS -- /* Read deleted status (bit) then return it to it's non-deleted -- * state before performing tags mini-ECC check. pt1.deleted is -- * inverted. -- */ -- deleted = !pt1.deleted; -- pt1.deleted = 1; --#else -- (void) deleted; /* not used */ --#endif -- -- /* Check the packed tags mini-ECC and correct if necessary/possible. -- */ -- retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1); -- switch (retval) { -- case 0: -- /* no tags error, use MTD result */ -- break; -- case 1: -- /* recovered tags-ECC error */ -- dev->tagsEccFixed++; -- eccres = YAFFS_ECC_RESULT_FIXED; -- break; -- default: -- /* unrecovered tags-ECC error */ -- dev->tagsEccUnfixed++; -- return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); -- } -- -- /* Unpack the tags to extended form and set ECC result. -- * [set shouldBeFF just to keep yaffs_UnpackTags1 happy] -- */ -- pt1.shouldBeFF = 0xFFFFFFFF; -- yaffs_UnpackTags1(etags, &pt1); -- etags->eccResult = eccres; -- -- /* Set deleted state. -- */ --#ifndef CONFIG_YAFFS_9BYTE_TAGS -- etags->chunkDeleted = deleted; --#else -- etags->chunkDeleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7); --#endif -- return YAFFS_OK; --} -- --/* Mark a block bad. -- * -- * This is a persistant state. -- * Use of this function should be rare. -- * -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk; -- int retval; -- -- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo); -- -- retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo); -- return (retval) ? YAFFS_FAIL : YAFFS_OK; --} -- --/* Check any MTD prerequists. -- * -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --static int nandmtd1_TestPrerequists(struct mtd_info * mtd) --{ -- /* 2.6.18 has mtd->ecclayout->oobavail */ -- /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ -- int oobavail = mtd->ecclayout->oobavail; -- -- if (oobavail < YTAG1_SIZE) { -- yaffs_trace(YAFFS_TRACE_ERROR, -- "mtd device has only %d bytes for tags, need %d", -- oobavail, YTAG1_SIZE); -- return YAFFS_FAIL; -- } -- return YAFFS_OK; --} -- --/* Query for the current state of a specific block. -- * -- * Examine the tags of the first chunk of the block and return the state: -- * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad -- * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use -- * - YAFFS_BLOCK_STATE_EMPTY, the block is clean -- * -- * Always returns YAFFS_OK. -- */ --int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * pState, int *pSequenceNumber) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int chunkNo = blockNo * dev->nChunksPerBlock; -- yaffs_ExtendedTags etags; -- int state = YAFFS_BLOCK_STATE_DEAD; -- int seqnum = 0; -- int retval; -- -- /* We don't yet have a good place to test for MTD config prerequists. -- * Do it here as we are called during the initial scan. -- */ -- if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { -- return YAFFS_FAIL; -- } -- -- retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); -- if (etags.blockBad) { -- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, -- "block %d is marked bad", blockNo); -- state = YAFFS_BLOCK_STATE_DEAD; -- } -- else if (etags.chunkUsed) { -- state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; -- seqnum = etags.sequenceNumber; -- } -- else { -- state = YAFFS_BLOCK_STATE_EMPTY; -- } -- -- *pState = state; -- *pSequenceNumber = seqnum; -- -- /* query always succeeds */ -- return YAFFS_OK; --} -- --#endif /*KERNEL_VERSION*/ -- ----Boundary-00=_5LbTGmt62YoutxM-- -- -- -- -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,363 +0,0 @@ --/* -- * YAFFS: Yet another FFS. A NAND-flash specific file system. -- * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND. -- * -- * Copyright (C) 2002 Aleph One Ltd. -- * for Toby Churchill Ltd and Brightstar Engineering -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --/* -- * This module provides the interface between yaffs_nand.c and the -- * MTD API. This version is used when the MTD interface supports the -- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, -- * and we have small-page NAND device. -- * -- * These functions are invoked via function pointers in yaffs_nand.c. -- * This replaces functionality provided by functions in yaffs_mtdif.c -- * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are -- * called in yaffs_mtdif.c when the function pointers are NULL. -- * We assume the MTD layer is performing ECC (useNANDECC is true). -- */ -- --#include "yportenv.h" --#include "yaffs_guts.h" --#include "yaffs_packedtags1.h" --#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC -- --#include "linux/kernel.h" --#include "linux/version.h" --#include "linux/types.h" --#include "linux/mtd/mtd.h" -- --/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- --const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $"; -- --#ifndef CONFIG_YAFFS_9BYTE_TAGS --# define YTAG1_SIZE 8 --#else --# define YTAG1_SIZE 9 --#endif -- --#if 0 --/* Use the following nand_ecclayout with MTD when using -- * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout. -- * If you have existing Yaffs images and the byte order differs from this, -- * adjust 'oobfree' to match your existing Yaffs data. -- * -- * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the -- * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to -- * the 9th byte. -- * -- * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 -- * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P -- * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus -- * byte and B is the small-page bad-block indicator byte. -- */ --static struct nand_ecclayout nand_oob_16 = { -- .eccbytes = 6, -- .eccpos = { 8, 9, 10, 13, 14, 15 }, -- .oobavail = 9, -- .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } --}; --#endif -- --/* Write a chunk (page) of data to NAND. -- * -- * Caller always provides ExtendedTags data which are converted to a more -- * compact (packed) form for storage in NAND. A mini-ECC runs over the -- * contents of the tags meta-data; used to valid the tags when read. -- * -- * - Pack ExtendedTags to PackedTags1 form -- * - Compute mini-ECC for PackedTags1 -- * - Write data and packed tags to NAND. -- * -- * Note: Due to the use of the PackedTags1 meta-data which does not include -- * a full sequence number (as found in the larger PackedTags2 form) it is -- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as -- * discarded and dirty. This is not ideal: newer NAND parts are supposed -- * to be written just once. When Yaffs performs this operation, this -- * function is called with a NULL data pointer -- calling MTD write_oob -- * without data is valid usage (2.6.17). -- * -- * Any underlying MTD error results in YAFFS_FAIL. -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, -- int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int chunkBytes = dev->nDataBytesPerChunk; -- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -- struct mtd_oob_ops ops; -- yaffs_PackedTags1 pt1; -- int retval; -- -- /* we assume that PackedTags1 and yaffs_Tags are compatible */ -- compile_time_assertion(sizeof(yaffs_PackedTags1) == 12); -- compile_time_assertion(sizeof(yaffs_Tags) == 8); -- -- dev->nPageWrites++; -- -- yaffs_PackTags1(&pt1, etags); -- yaffs_CalcTagsECC((yaffs_Tags *)&pt1); -- -- /* When deleting a chunk, the upper layer provides only skeletal -- * etags, one with chunkDeleted set. However, we need to update the -- * tags, not erase them completely. So we use the NAND write property -- * that only zeroed-bits stick and set tag bytes to all-ones and -- * zero just the (not) deleted bit. -- */ --#ifndef CONFIG_YAFFS_9BYTE_TAGS -- if (etags->chunkDeleted) { -- memset(&pt1, 0xff, 8); -- /* clear delete status bit to indicate deleted */ -- pt1.deleted = 0; -- } --#else -- ((__u8 *)&pt1)[8] = 0xff; -- if (etags->chunkDeleted) { -- memset(&pt1, 0xff, 8); -- /* zero pageStatus byte to indicate deleted */ -- ((__u8 *)&pt1)[8] = 0; -- } --#endif -- -- memset(&ops, 0, sizeof(ops)); -- ops.mode = MTD_OOB_AUTO; -- ops.len = (data) ? chunkBytes : 0; -- ops.ooblen = YTAG1_SIZE; -- ops.datbuf = (__u8 *)data; -- ops.oobbuf = (__u8 *)&pt1; -- -- retval = mtd->write_oob(mtd, addr, &ops); -- if (retval) { -- yaffs_trace(YAFFS_TRACE_MTD, -- "write_oob failed, chunk %d, mtd error %d\n", -- chunkInNAND, retval); -- } -- return retval ? YAFFS_FAIL : YAFFS_OK; --} -- --/* Return with empty ExtendedTags but add eccResult. -- */ --static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) --{ -- if (etags) { -- memset(etags, 0, sizeof(*etags)); -- etags->eccResult = eccResult; -- } -- return retval; --} -- --/* Read a chunk (page) from NAND. -- * -- * Caller expects ExtendedTags data to be usable even on error; that is, -- * all members except eccResult and blockBad are zeroed. -- * -- * - Check ECC results for data (if applicable) -- * - Check for blank/erased block (return empty ExtendedTags if blank) -- * - Check the PackedTags1 mini-ECC (correct if necessary/possible) -- * - Convert PackedTags1 to ExtendedTags -- * - Update eccResult and blockBad members to refect state. -- * -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, -- int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int chunkBytes = dev->nDataBytesPerChunk; -- loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; -- int eccres = YAFFS_ECC_RESULT_NO_ERROR; -- struct mtd_oob_ops ops; -- yaffs_PackedTags1 pt1; -- int retval; -- int deleted; -- -- dev->nPageReads++; -- -- memset(&ops, 0, sizeof(ops)); -- ops.mode = MTD_OOB_AUTO; -- ops.len = (data) ? chunkBytes : 0; -- ops.ooblen = YTAG1_SIZE; -- ops.datbuf = data; -- ops.oobbuf = (__u8 *)&pt1; -- --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) -- /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; -- * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. -- */ -- ops.len = (ops.datbuf) ? ops.len : ops.ooblen; --#endif -- /* Read page and oob using MTD. -- * Check status and determine ECC result. -- */ -- retval = mtd->read_oob(mtd, addr, &ops); -- if (retval) { -- yaffs_trace(YAFFS_TRACE_MTD, -- "read_oob failed, chunk %d, mtd error %d\n", -- chunkInNAND, retval); -- } -- -- switch (retval) { -- case 0: -- /* no error */ -- break; -- -- case -EUCLEAN: -- /* MTD's ECC fixed the data */ -- eccres = YAFFS_ECC_RESULT_FIXED; -- dev->eccFixed++; -- break; -- -- case -EBADMSG: -- /* MTD's ECC could not fix the data */ -- dev->eccUnfixed++; -- /* fall into... */ -- default: -- rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); -- etags->blockBad = (mtd->block_isbad)(mtd, addr); -- return YAFFS_FAIL; -- } -- -- /* Check for a blank/erased chunk. -- */ -- if (yaffs_CheckFF((__u8 *)&pt1, 8)) { -- /* when blank, upper layers want eccResult to be <= NO_ERROR */ -- return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); -- } -- --#ifndef CONFIG_YAFFS_9BYTE_TAGS -- /* Read deleted status (bit) then return it to it's non-deleted -- * state before performing tags mini-ECC check. pt1.deleted is -- * inverted. -- */ -- deleted = !pt1.deleted; -- pt1.deleted = 1; --#else -- deleted = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7); --#endif -- -- /* Check the packed tags mini-ECC and correct if necessary/possible. -- */ -- retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1); -- switch (retval) { -- case 0: -- /* no tags error, use MTD result */ -- break; -- case 1: -- /* recovered tags-ECC error */ -- dev->tagsEccFixed++; -- if (eccres == YAFFS_ECC_RESULT_NO_ERROR) -- eccres = YAFFS_ECC_RESULT_FIXED; -- break; -- default: -- /* unrecovered tags-ECC error */ -- dev->tagsEccUnfixed++; -- return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); -- } -- -- /* Unpack the tags to extended form and set ECC result. -- * [set shouldBeFF just to keep yaffs_UnpackTags1 happy] -- */ -- pt1.shouldBeFF = 0xFFFFFFFF; -- yaffs_UnpackTags1(etags, &pt1); -- etags->eccResult = eccres; -- -- /* Set deleted state */ -- etags->chunkDeleted = deleted; -- return YAFFS_OK; --} -- --/* Mark a block bad. -- * -- * This is a persistant state. -- * Use of this function should be rare. -- * -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk; -- int retval; -- -- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo); -- -- retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo); -- return (retval) ? YAFFS_FAIL : YAFFS_OK; --} -- --/* Check any MTD prerequists. -- * -- * Returns YAFFS_OK or YAFFS_FAIL. -- */ --static int nandmtd1_TestPrerequists(struct mtd_info * mtd) --{ -- /* 2.6.18 has mtd->ecclayout->oobavail */ -- /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ -- int oobavail = mtd->ecclayout->oobavail; -- -- if (oobavail < YTAG1_SIZE) { -- yaffs_trace(YAFFS_TRACE_ERROR, -- "mtd device has only %d bytes for tags, need %d\n", -- oobavail, YTAG1_SIZE); -- return YAFFS_FAIL; -- } -- return YAFFS_OK; --} -- --/* Query for the current state of a specific block. -- * -- * Examine the tags of the first chunk of the block and return the state: -- * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad -- * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use -- * - YAFFS_BLOCK_STATE_EMPTY, the block is clean -- * -- * Always returns YAFFS_OK. -- */ --int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * pState, int *pSequenceNumber) --{ -- struct mtd_info * mtd = dev->genericDevice; -- int chunkNo = blockNo * dev->nChunksPerBlock; -- yaffs_ExtendedTags etags; -- int state = YAFFS_BLOCK_STATE_DEAD; -- int seqnum = 0; -- int retval; -- -- /* We don't yet have a good place to test for MTD config prerequists. -- * Do it here as we are called during the initial scan. -- */ -- if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { -- return YAFFS_FAIL; -- } -- -- retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); -- if (etags.blockBad) { -- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, -- "block %d is marked bad", blockNo); -- state = YAFFS_BLOCK_STATE_DEAD; -- } -- else if (etags.chunkUsed) { -- state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; -- seqnum = etags.sequenceNumber; -- } -- else { -- state = YAFFS_BLOCK_STATE_EMPTY; -- } -- -- *pState = state; -- *pSequenceNumber = seqnum; -- -- /* query always succeeds */ -- return YAFFS_OK; --} -- --#endif /*KERNEL_VERSION*/ -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.h linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif1.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif1.h 1970-01-01 01:00:00.000000000 +0100 -@@ -1,28 +0,0 @@ --/* -- * 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 -- * -- * 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_MTDIF1_H__ --#define __YAFFS_MTDIF1_H__ -- --int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, const yaffs_ExtendedTags * tags); -- --int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -- __u8 * data, yaffs_ExtendedTags * tags); -- --int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); -- --int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * state, int *sequenceNumber); -- --#endif -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.c linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.c 2009-04-21 15:01:02.000000000 +0200 -@@ -14,19 +14,152 @@ - /* 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.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; - - #include "yportenv.h" -- -- - #include "yaffs_mtdif2.h" -- - #include "linux/mtd/mtd.h" - #include "linux/types.h" - #include "linux/time.h" - - #include "yaffs_packedtags2.h" - -+#define PT2_BYTES 25 -+ -+void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) -+{ -+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -+ int i, j = 0, k, n; -+ __u8 pt2_byte_buf[PT2_BYTES]; -+ -+ /* Pack buffer with 0xff */ -+ for (i = 0; i < mtd->oobsize; i++) -+ dev->spareBuffer[i] = 0xff; -+ -+ if (!is_raw) { -+ *((unsigned int *) &dev->spareBuffer[0]) = pt->t.sequenceNumber; -+ *((unsigned int *) &dev->spareBuffer[4]) = pt->t.objectId; -+ *((unsigned int *) &dev->spareBuffer[8]) = pt->t.chunkId; -+ *((unsigned int *) &dev->spareBuffer[12]) = pt->t.byteCount; -+ dev->spareBuffer[16] = pt->ecc.colParity; -+ dev->spareBuffer[17] = pt->ecc.lineParity & 0xff; -+ dev->spareBuffer[18] = (pt->ecc.lineParity >> 8) & 0xff; -+ dev->spareBuffer[19] = (pt->ecc.lineParity >> 16) & 0xff; -+ dev->spareBuffer[20] = (pt->ecc.lineParity >> 24) & 0xff; -+ dev->spareBuffer[21] = pt->ecc.lineParityPrime & 0xff; -+ dev->spareBuffer[22] = (pt->ecc.lineParityPrime >> 8) & 0xff; -+ dev->spareBuffer[23] = (pt->ecc.lineParityPrime >> 16) & 0xff; -+ dev->spareBuffer[24] = (pt->ecc.lineParityPrime >> 24) & 0xff; -+ } else { -+ *((unsigned int *) &pt2_byte_buf[0]) = pt->t.sequenceNumber; -+ *((unsigned int *) &pt2_byte_buf[4]) = pt->t.objectId; -+ *((unsigned int *) &pt2_byte_buf[8]) = pt->t.chunkId; -+ *((unsigned int *) &pt2_byte_buf[12]) = pt->t.byteCount; -+ pt2_byte_buf[16] = pt->ecc.colParity; -+ pt2_byte_buf[17] = pt->ecc.lineParity & 0xff; -+ pt2_byte_buf[18] = (pt->ecc.lineParity >> 8) & 0xff; -+ pt2_byte_buf[19] = (pt->ecc.lineParity >> 16) & 0xff; -+ pt2_byte_buf[20] = (pt->ecc.lineParity >> 24) & 0xff; -+ pt2_byte_buf[21] = pt->ecc.lineParityPrime & 0xff; -+ pt2_byte_buf[22] = (pt->ecc.lineParityPrime >> 8) & 0xff; -+ pt2_byte_buf[23] = (pt->ecc.lineParityPrime >> 16) & 0xff; -+ pt2_byte_buf[24] = (pt->ecc.lineParityPrime >> 24) & 0xff; -+ -+// k = mtd->oobinfo.oobfree[j][0]; -+// n = mtd->oobinfo.oobfree[j][1]; -+ -+ k = mtd->ecclayout->oobfree[j].offset; -+ n = mtd->ecclayout->oobfree[j].length; -+ if (n == 0) { -+ T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); -+ YBUG(); -+ } -+ -+ for (i = 0; i < PT2_BYTES; i++) { -+ if (n == 0) { -+ j++; -+// k = mtd->oobinfo.oobfree[j][0]; -+// n = mtd->oobinfo.oobfree[j][1]; -+ k = mtd->ecclayout->oobfree[j].offset; -+ n = mtd->ecclayout->oobfree[j].length; -+ -+ if (n == 0) { -+ T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); -+ YBUG(); -+ } -+ } -+ dev->spareBuffer[k++] = pt2_byte_buf[i]; -+ n--; -+ } -+ } -+ -+} -+ -+void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) -+{ -+ struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -+ int i, j = 0, k, n; -+ __u8 pt2_byte_buf[PT2_BYTES]; -+ -+ -+ if (!is_raw) { -+ pt->t.sequenceNumber = *((unsigned int *) &dev->spareBuffer[0]); -+ pt->t.objectId = *((unsigned int *) &dev->spareBuffer[4]); -+ pt->t.chunkId = *((unsigned int *) &dev->spareBuffer[8]); -+ pt->t.byteCount = *((unsigned int *) &dev->spareBuffer[12]); -+ pt->ecc.colParity = dev->spareBuffer[16]; -+ pt->ecc.lineParity = (dev->spareBuffer[17] & 0x000000ff) | -+ ((dev->spareBuffer[18] << 8) & 0x0000ff00) | -+ ((dev->spareBuffer[19] << 16) & 0x00ff0000) | -+ ((dev->spareBuffer[20] << 24) & 0xff000000); -+ pt->ecc.lineParityPrime = (dev->spareBuffer[21] & 0x000000ff) | -+ ((dev->spareBuffer[22] << 8) & 0x0000ff00) | -+ ((dev->spareBuffer[23] << 16) & 0x00ff0000) | -+ ((dev->spareBuffer[24] << 24) & 0xff000000); -+ } else { -+// k = mtd->oobinfo.oobfree[j][0]; -+// n = mtd->oobinfo.oobfree[j][1]; -+ -+ k = mtd->ecclayout->oobfree[j].offset; -+ n = mtd->ecclayout->oobfree[j].length; -+ -+ if (n == 0) { -+ T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); -+ YBUG(); -+ } -+ -+ for (i = 0; i < PT2_BYTES; i++) { -+ if (n == 0) { -+ j++; -+// k = mtd->oobinfo.oobfree[j][0]; -+// n = mtd->oobinfo.oobfree[j][1]; -+ k = mtd->ecclayout->oobfree[j].offset; -+ n = mtd->ecclayout->oobfree[j].length; -+ -+ if (n == 0) { -+ T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); -+ YBUG(); -+ } -+ } -+ pt2_byte_buf[i] = dev->spareBuffer[k++]; -+ n--; -+ } -+ pt->t.sequenceNumber = *((unsigned int *) &pt2_byte_buf[0]); -+ pt->t.objectId = *((unsigned int *) &pt2_byte_buf[4]); -+ pt->t.chunkId = *((unsigned int *) &pt2_byte_buf[8]); -+ pt->t.byteCount = *((unsigned int *) &pt2_byte_buf[12]); -+ pt->ecc.colParity = pt2_byte_buf[16]; -+ pt->ecc.lineParity = (pt2_byte_buf[17] & 0x000000ff) | -+ ((pt2_byte_buf[18] << 8) & 0x0000ff00) | -+ ((pt2_byte_buf[19] << 16) & 0x00ff0000) | -+ ((pt2_byte_buf[20] << 24) & 0xff000000); -+ pt->ecc.lineParityPrime = (pt2_byte_buf[21] & 0x000000ff) | -+ ((pt2_byte_buf[22] << 8) & 0x0000ff00) | -+ ((pt2_byte_buf[23] << 16) & 0x00ff0000) | -+ ((pt2_byte_buf[24] << 24) & 0xff000000); -+ } -+} -+ - int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, - const __u8 * data, - const yaffs_ExtendedTags * tags) -@@ -38,9 +171,7 @@ - size_t dummy; - #endif - int retval = 0; -- -- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -- -+ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; - yaffs_PackedTags2 pt; - - T(YAFFS_TRACE_MTD, -@@ -55,12 +186,14 @@ - BUG(); /* both tags and data should always be present */ - - if (data) { -+ nandmtd2_pt2buf(dev, &pt, 0); //modify - ops.mode = MTD_OOB_AUTO; - ops.ooblen = sizeof(pt); - ops.len = dev->nDataBytesPerChunk; - ops.ooboffs = 0; - ops.datbuf = (__u8 *)data; -- ops.oobbuf = (void *)&pt; -+// ops.oobbuf = (void *)&pt; //modify -+ ops.oobbuf = (void *)dev->spareBuffer; //modify - retval = mtd->write_oob(mtd, addr, &ops); - } else - BUG(); /* both tags and data should always be present */ -@@ -70,24 +203,27 @@ - } - - if (data && tags) { -+ nandmtd2_pt2buf(dev, &pt, 0); - if (dev->useNANDECC) - retval = - mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -- &dummy, data, (__u8 *) & pt, NULL); -+ &dummy, data, dev->spareBuffer, NULL); - else - retval = - mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -- &dummy, data, (__u8 *) & pt, NULL); -+ &dummy, data, dev->spareBuffer, NULL); - } else { -- if (data) -+ if (data) { - retval = - mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, - data); -- if (tags) -+ } -+ if (tags) { -+ nandmtd2_pt2buf(dev, &pt, 1); - retval = - mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, -- (__u8 *) & pt); -- -+ dev->spareBuffer); -+ } - } - #endif - -@@ -104,11 +240,9 @@ - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) - struct mtd_oob_ops ops; - #endif -- size_t dummy; -+ size_mtd_t dummy; - int retval = 0; -- -- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -- -+ loff_mtd_t addr = ((loff_mtd_t) chunkInNAND) * dev->nDataBytesPerChunk; - yaffs_PackedTags2 pt; - - T(YAFFS_TRACE_MTD, -@@ -128,6 +262,7 @@ - ops.datbuf = data; - ops.oobbuf = dev->spareBuffer; - retval = mtd->read_oob(mtd, addr, &ops); -+ nandmtd2_buf2pt(dev, &pt, 0); //modify by yliu - } - #else - if (data && tags) { -@@ -142,23 +277,25 @@ - &dummy, data, dev->spareBuffer, - NULL); - } -+ nandmtd2_buf2pt(dev, &pt, 0); - } else { -- if (data) -+ if (data) { - retval = - mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, - data); -- if (tags) -+ } -+ if (tags) { - retval = - mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, - dev->spareBuffer); -+ nandmtd2_buf2pt(dev, &pt, 1); -+ } - } - #endif - -- memcpy(&pt, dev->spareBuffer, sizeof(pt)); -- - if (tags) - yaffs_UnpackTags2(tags, &pt); -- -+ - if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) - tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; - -@@ -177,7 +314,7 @@ - - retval = - mtd->block_markbad(mtd, -- blockNo * dev->nChunksPerBlock * -+ (u64)blockNo * dev->nChunksPerBlock * - dev->nDataBytesPerChunk); - - if (retval == 0) -@@ -195,11 +332,11 @@ - - T(YAFFS_TRACE_MTD, - (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); -+ - retval = - mtd->block_isbad(mtd, -- blockNo * dev->nChunksPerBlock * -+ (u64)blockNo * dev->nChunksPerBlock * - dev->nDataBytesPerChunk); -- - if (retval) { - T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); - -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.h linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_mtdif2.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_mtdif2.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_nand.c linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_nand.c 2009-04-21 14:57:10.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.c 2009-04-21 15:01:02.000000000 +0200 -@@ -10,9 +10,9 @@ - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -- -+ - 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.1.1.1 2008-03-28 04:29:21 jlwei Exp $"; - - #include "yaffs_nand.h" - #include "yaffs_tagscompat.h" -@@ -25,9 +25,9 @@ - { - int result; - yaffs_ExtendedTags localTags; -- -+ - int realignedChunkInNAND = chunkInNAND - dev->chunkOffset; -- -+ - /* If there are no tags provided, use local tags to get prioritised gc working */ - if(!tags) - tags = &localTags; -@@ -39,14 +39,14 @@ - result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev, - realignedChunkInNAND, - buffer, -- tags); -- if(tags && -- tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ -+ tags); - -+ if(tags && -+ tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); - yaffs_HandleChunkError(dev,bi); - } -- -+ - return result; - } - -@@ -57,7 +57,7 @@ - { - chunkInNAND -= dev->chunkOffset; - -- -+ - if (tags) { - tags->sequenceNumber = dev->sequenceNumber; - tags->chunkUsed = 1; -@@ -131,4 +131,4 @@ - } - - -- -+ -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_nand.h linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_nand.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_nand.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_nandemul2k.h linux-2.6.24.7.new/fs/yaffs2/yaffs_nandemul2k.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_nandemul2k.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_nandemul2k.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_packedtags1.h linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags1.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_packedtags1.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags1.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.c linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.c 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.c 2009-04-21 15:01:02.000000000 +0200 -@@ -40,7 +40,8 @@ - static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) - { - T(YAFFS_TRACE_MTD, -- (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), -+// T(YAFFS_TRACE_ALWAYS, -+ (TSTR("packed tags obj %x chunk %x byte %x seq %x" TENDSTR), - pt->t.objectId, pt->t.chunkId, pt->t.byteCount, - pt->t.sequenceNumber)); - } -@@ -48,9 +49,10 @@ - static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) - { - T(YAFFS_TRACE_MTD, -+// T(YAFFS_TRACE_ALWAYS, - (TSTR -- ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " -- "%d del %d ser %d seq %d" -+ ("ext.tags eccres %x blkbad %x chused %x obj %x chunk%x byte " -+ "%x del %x ser %x seq %x" - TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId, - t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, - t->sequenceNumber)); -@@ -89,10 +91,10 @@ - } - } - -- yaffs_DumpPackedTags2(pt); -- yaffs_DumpTags2(t); -+// yaffs_DumpPackedTags2(pt); -+// yaffs_DumpTags2(t); - --#ifndef YAFFS_IGNORE_TAGS_ECC -+#if !defined(YAFFS_IGNORE_TAGS_ECC) && !defined(CONFIG_MTD_HW_BCH_ECC) - { - yaffs_ECCCalculateOther((unsigned char *)&pt->t, - sizeof(yaffs_PackedTags2TagsPart), -@@ -103,14 +105,11 @@ - - void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) - { -- -- memset(t, 0, sizeof(yaffs_ExtendedTags)); -- - yaffs_InitialiseTags(t); - - if (pt->t.sequenceNumber != 0xFFFFFFFF) { - /* Page is in use */ --#ifdef YAFFS_IGNORE_TAGS_ECC -+#if defined(YAFFS_IGNORE_TAGS_ECC) || defined(CONFIG_MTD_HW_BCH_ECC) - { - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; - } -@@ -118,20 +117,23 @@ - { - yaffs_ECCOther ecc; - int result; -+#if defined(CONFIG_YAFFS_ECC_HAMMING) - yaffs_ECCCalculateOther((unsigned char *)&pt->t, - sizeof - (yaffs_PackedTags2TagsPart), - &ecc); -+#endif - result = - yaffs_ECCCorrectOther((unsigned char *)&pt->t, - sizeof - (yaffs_PackedTags2TagsPart), - &pt->ecc, &ecc); -+ - switch(result){ -- case 0: -- t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -+ case 0: -+ t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; - break; -- case 1: -+ case 1: - t->eccResult = YAFFS_ECC_RESULT_FIXED; - break; - case -1: -@@ -175,8 +177,8 @@ - } - } - } -- -+// printk("\n TAG %d",t->chunkUsed); - yaffs_DumpPackedTags2(pt); - yaffs_DumpTags2(t); -- -+// printk("\n TAG %d",t->chunkUsed); - } -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.h linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_packedtags2.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_packedtags2.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_qsort.c linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_qsort.c 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.c 2009-04-21 15:01:02.000000000 +0200 -@@ -50,7 +50,7 @@ - static __inline void - swapfunc(char *a, char *b, int n, int swaptype) - { -- if (swaptype <= 1) -+ if (swaptype <= 1) - swapcode(long, a, b, n) - else - swapcode(char, a, b, n) -@@ -74,13 +74,8 @@ - :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); - } - --#ifndef min --#define min(a,b) (((a) < (b)) ? (a) : (b)) --#endif -- - void --yaffs_qsort(void *aa, size_t n, size_t es, -- int (*cmp)(const void *, const void *)) -+qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)) - { - char *pa, *pb, *pc, *pd, *pl, *pm, *pn; - int d, r, swaptype, swap_cnt; -@@ -137,7 +132,7 @@ - } - if (swap_cnt == 0) { /* Switch to insertion sort */ - for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) -- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; -+ for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; - pl -= es) - swap(pl, pl - es); - return; -@@ -149,12 +144,12 @@ - r = min((long)(pd - pc), (long)(pn - pd - es)); - vecswap(pb, pn - r, r); - if ((r = pb - pa) > es) -- yaffs_qsort(a, r / es, es, cmp); -- if ((r = pd - pc) > es) { -+ qsort(a, r / es, es, cmp); -+ if ((r = pd - pc) > es) { - /* Iterate rather than recurse to save stack space */ - a = pn - r; - n = r / es; - goto loop; - } --/* yaffs_qsort(pn - r, r / es, es, cmp);*/ -+/* qsort(pn - r, r / es, es, cmp);*/ - } -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_qsort.h linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_qsort.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_qsort.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -@@ -17,7 +17,7 @@ - #ifndef __YAFFS_QSORT_H__ - #define __YAFFS_QSORT_H__ - --extern void yaffs_qsort (void *const base, size_t total_elems, size_t size, -+extern void qsort (void *const base, size_t total_elems, size_t size, - int (*cmp)(const void *, const void *)); - - #endif -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.c linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.c ---- linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.c 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.c 2009-04-21 15:01:02.000000000 +0200 -@@ -45,7 +45,7 @@ - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 - }; - --int yaffs_CountBits(__u8 x) -+static int yaffs_CountBits(__u8 x) - { - int retVal; - retVal = yaffs_countBitsTable[x]; -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.h linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_tagscompat.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_tagscompat.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -@@ -33,8 +33,4 @@ - int blockNo, yaffs_BlockState * - state, int *sequenceNumber); - --void yaffs_CalcTagsECC(yaffs_Tags * tags); --int yaffs_CheckECCOnTags(yaffs_Tags * tags); --int yaffs_CountBits(__u8 byte); -- - #endif -diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_tagsvalidity.h linux-2.6.24.7.new/fs/yaffs2/yaffs_tagsvalidity.h ---- linux-2.6.24.7/fs/yaffs2/yaffs_tagsvalidity.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_tagsvalidity.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yaffsinterface.h linux-2.6.24.7.new/fs/yaffs2/yaffsinterface.h ---- linux-2.6.24.7/fs/yaffs2/yaffsinterface.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yaffsinterface.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -diff -urN linux-2.6.24.7/fs/yaffs2/yportenv.h linux-2.6.24.7.new/fs/yaffs2/yportenv.h ---- linux-2.6.24.7/fs/yaffs2/yportenv.h 2009-04-09 17:39:09.000000000 +0200 -+++ linux-2.6.24.7.new/fs/yaffs2/yportenv.h 2009-04-21 15:01:02.000000000 +0200 -@@ -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 -@@ -32,7 +32,6 @@ - #endif - #include - #include --#include - #include - #include - #include -@@ -42,7 +41,6 @@ - #define _Y(x) x - #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) - #define yaffs_strlen(s) strlen(s) - #define yaffs_sprintf sprintf - #define yaffs_toupper(a) toupper(a) -@@ -62,7 +60,7 @@ - // KR - added for use in scan so processes aren't blocked indefinitely. - #define YYIELD() schedule() - --#define YAFFS_ROOT_MODE 0666 -+#define YAFFS_ROOT_MODE 0666 - #define YAFFS_LOSTNFOUND_MODE 0666 - - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -@@ -80,14 +78,6 @@ - #define TSTR(x) KERN_WARNING x - #define TOUT(p) printk p - --#define yaffs_trace(mask, fmt, args...) \ -- do { if ((mask) & (yaffs_traceMask|YAFFS_TRACE_ERROR)) \ -- printk(KERN_WARNING "yaffs: " fmt, ## args); \ -- } while (0) -- --#define compile_time_assertion(assertion) \ -- ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; }) -- - #elif defined CONFIG_YAFFS_DIRECT - - /* Direct interface */ -@@ -142,15 +132,9 @@ - - #endif - --/* see yaffs_fs.c */ --extern unsigned int yaffs_traceMask; --extern unsigned int yaffs_wr_attempts; -- --/* -- * Tracing flags. -- * The flags masked in YAFFS_TRACE_ALWAYS are always traced. -- */ -+extern unsigned yaffs_traceMask; - -+#define YAFFS_TRACE_ERROR 0x00000001 - #define YAFFS_TRACE_OS 0x00000002 - #define YAFFS_TRACE_ALLOCATE 0x00000004 - #define YAFFS_TRACE_SCAN 0x00000008 -@@ -166,19 +150,10 @@ - #define YAFFS_TRACE_SCAN_DEBUG 0x00002000 - #define YAFFS_TRACE_MTD 0x00004000 - #define YAFFS_TRACE_CHECKPOINT 0x00008000 -- --#define YAFFS_TRACE_VERIFY 0x00010000 --#define YAFFS_TRACE_VERIFY_NAND 0x00020000 --#define YAFFS_TRACE_VERIFY_FULL 0x00040000 --#define YAFFS_TRACE_VERIFY_ALL 0x000F0000 -- -- --#define YAFFS_TRACE_ERROR 0x40000000 -+#define YAFFS_TRACE_ALWAYS 0x40000000 - #define YAFFS_TRACE_BUG 0x80000000 --#define YAFFS_TRACE_ALWAYS 0xF0000000 -- - --#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0) -+#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ERROR)) TOUT(p);} while(0) - - #ifndef CONFIG_YAFFS_WINCE - #define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))