1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-25 08:34:09 +02:00
openwrt-xburst/target/linux/xburst/patches-2.6.24/002-yaffs2_dists.patch
2009-10-28 03:12:54 +08:00

8843 lines
241 KiB
Diff

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 <Martin.Fouts@palmsource.com>
+ * Created by Martin Fouts <Martin.Fouts@palmsource.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1 as
@@ -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 <charles@aleph1.co.uk>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+
+## 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 <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#include <mtd/mtd-user.h>
+#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 <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * Nick Bane modifications flagged NCB
+ *
+ * Endian handling patches by James Ng.
+ *
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#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 <string.h>
+
+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<<symsize))
+ goto done;
+ if(prim <= 0 || prim >= (1<<symsize))
+ goto done;
+ if(nroots < 0 || nroots >= (1<<symsize))
+ goto done;
+ if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
+ goto done;
+
+ rs = (struct rs *)malloc(sizeof(struct rs));
+// rs = (struct rs *)rs0;
+ if(rs == ((void *)0))
+ goto done;
+ rs->mm = symsize;
+ rs->nn = (1<<symsize)-1;
+ rs->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;i<rs->nn;i++){
+ rs->index_of[sr] = i;
+ rs->alpha_to[i] = sr;
+ sr <<= 1;
+ if(sr & (1<<symsize))
+ sr ^= gfpoly;
+ sr &= rs->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<<mm)-1) */
+ data_t *alpha_to; /* log lookup table */
+ data_t *index_of; /* Antilog lookup table */
+ data_t *genpoly; /* Generator polynomial */
+ int nroots; /* Number of generator roots = number of parity symbols */
+ int fcr; /* First consecutive root, index form */
+ int prim; /* Primitive element, index form */
+ int iprim; /* prim-th root of 1, index form */
+ int pad; /* Padding bytes in shortened block */
+};
+
+void encode_rs(void *p,data_t *data, unsigned short *bb);
+struct rs *init_rs_int(int symsize,int gfpoly,int fcr,int prim,int nroots,int pad);
+void free_rs_int(void *p);
+
+#endif /* __SSFDC_RS_ECC_H__ */
diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_checkptrw.c linux-2.6.24.7.new/fs/yaffs2/yaffs_checkptrw.c
--- linux-2.6.24.7/fs/yaffs2/yaffs_checkptrw.c 2009-04-21 14:57:10.000000000 +0200
+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_checkptrw.c 2009-04-21 15:01:02.000000000 +0200
@@ -12,7 +12,7 @@
*/
const char *yaffs_checkptrw_c_version =
- "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $";
+ "$Id: yaffs_checkptrw.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $";
#include "yaffs_checkptrw.h"
@@ -22,27 +22,28 @@
{
int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
-
+
T(YAFFS_TRACE_CHECKPOINT,
(TSTR("checkpt blocks available = %d" TENDSTR),
blocksAvailable));
-
-
+
+
return (blocksAvailable <= 0) ? 0 : 1;
}
+
static int yaffs_CheckpointErase(yaffs_Device *dev)
{
-
+
int i;
+
-
- if(!dev->eraseBlockInNAND)
+ 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 <linux/rslib.h>
+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<<Symbolsize-1) - nroot - 26 = 1
+ */
+ rs_init_user = (void *) init_rs_int (5, 0x25, 1, 1, 4, 1);
+ encode_rs(rs_init_user, data5, par);
+ free_rs_int(rs_init_user);
+#endif
+}
+
+#ifdef __KERNEL__
+/*
+ * It does reed solomon ECC correction on 16 bytes of oob data
+ */
+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
+ yaffs_ECCOther * read_ecc,
+ const yaffs_ECCOther * test_ecc)
+{
+ unsigned short *par = (unsigned short *)&read_ecc->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 <linux/version.h>
@@ -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 <asm/uaccess.h>
#include "yportenv.h"
#include "yaffs_guts.h"
+unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS |
+ YAFFS_TRACE_BAD_BLOCKS/* |
+ YAFFS_TRACE_CHECKPOINT*/
+ /* | 0xFFFFFFFF */;
+
#include <linux/mtd/mtd.h>
#include "yaffs_mtdif.h"
-#include "yaffs_mtdif1.h"
#include "yaffs_mtdif2.h"
-unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;
-unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
-
-/* 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 <linux/rslib.h>
+#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 <MAX_MASK_NAME_LENGTH; x++, i++, pos++)
- substring[i] = *x;
- substring[i] = '\0';
for (i = 0; mask_flags[i].mask_name != NULL; i++) {
- if(strcmp(substring,mask_flags[i].mask_name) == 0){
+ len = strlen(mask_flags[i].mask_name);
+ if (strncmp(buf + pos, mask_flags[i].mask_name, len) == 0) {
mask_name = mask_flags[i].mask_name;
mask_bitfield = mask_flags[i].mask_bitfield;
done = 0;
@@ -2171,6 +2082,7 @@
}
if (mask_name != NULL) {
+ pos += len;
done = 0;
switch(add) {
case '-':
@@ -2190,9 +2102,7 @@
}
yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS;
-
- printk("new trace = 0x%08X\n",yaffs_traceMask);
-
+
if (rg & YAFFS_TRACE_ALWAYS) {
for (i = 0; mask_flags[i].mask_name != NULL; i++) {
char flag;
@@ -2266,6 +2176,16 @@
}
}
+#if defined(CONFIG_YAFFS_ECC_RS)
+ /* 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
+ */
+ rs_decoder = init_rs (5, 0x25, 1, 1, 4);
+#endif
return error;
}
@@ -2289,6 +2209,9 @@
fsinst++;
}
+#if defined(CONFIG_YAFFS_ECC_RS)
+ free_rs(rs_decoder);
+#endif
}
module_init(init_yaffs_fs)
diff -urN linux-2.6.24.7/fs/yaffs2/yaffs_guts.c linux-2.6.24.7.new/fs/yaffs2/yaffs_guts.c
--- linux-2.6.24.7/fs/yaffs2/yaffs_guts.c 2009-04-21 14:57:10.000000000 +0200
+++ linux-2.6.24.7.new/fs/yaffs2/yaffs_guts.c 2009-04-21 15:01:02.000000000 +0200
@@ -12,7 +12,7 @@
*/
const char *yaffs_guts_c_version =
- "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $";
+ "$Id: yaffs_guts.c,v 1.1.1.1 2008-03-28 04:29:21 jlwei Exp $";
#include "yportenv.h"
@@ -21,7 +21,7 @@
#include "yaffs_tagsvalidity.h"
#include "yaffs_tagscompat.h"
-#ifndef CONFIG_YAFFS_USE_OWN_SORT
+#ifndef CONFIG_YAFFS_OWN_SORT
#include "yaffs_qsort.h"
#endif
#include "yaffs_nand.h"
@@ -97,8 +97,6 @@
static void yaffs_VerifyFreeChunks(yaffs_Device * dev);
-static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
-
#ifdef YAFFS_PARANOID
static int yaffs_CheckFileSanity(yaffs_Object * in);
#else
@@ -110,13 +108,6 @@
static void yaffs_InvalidateCheckpoint(yaffs_Device *dev);
-static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,
- yaffs_ExtendedTags * tags);
-
-static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos);
-static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,
- yaffs_FileStructure * fStruct,
- __u32 chunkId);
/* Function to calculate chunk and offset */
@@ -140,73 +131,56 @@
YBUG();
}
-/* Function to return the number of shifts for a power of 2 greater than or equal
+/* Function to return the number of shifts for a power of 2 greater than or equal
* to the given number
* Note we don't try to cater for all possible numbers and this does not have to
* be hellishly efficient.
*/
-
+
static __u32 ShiftsGE(__u32 x)
{
int extraBits;
int nShifts;
-
+
nShifts = extraBits = 0;
-
+
while(x>1){
if(x & 1) extraBits++;
x>>=1;
nShifts++;
}
- if(extraBits)
+ if(extraBits)
nShifts++;
-
+
return nShifts;
}
/* Function to return the number of shifts to get a 1 in bit 0
*/
-
+
static __u32 ShiftDiv(__u32 x)
{
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<<YAFFS_TNODES_INTERNAL_BITS) + i);
- }
- }
- } else if (level == 0) {
- int i;
- yaffs_ExtendedTags tags;
- __u32 objectId = obj->objectId;
-
- chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS;
-
- for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
- __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
-
- if(theChunk > 0){
- /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
- yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
- 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<<dev->tnodeWidth)-1;
-
+
/* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
* so if the bitwidth of the
* chunk range we're using is greater than 16 we need
* to figure out chunk shift and chunkGroupSize
*/
-
+
if (bits <= dev->tnodeWidth)
dev->chunkGroupBits = 0;
else
dev->chunkGroupBits = bits - dev->tnodeWidth;
-
+
dev->chunkGroupSize = 1 << dev->chunkGroupBits;
@@ -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 <ian@brightstareng.com>)
- id 1Hp380-00011e-T6
- for david.goodenough@linkchoose.co.uk; Fri, 18 May 2007 15:08:21 +0100
-Received: from localhost (localhost.localdomain [127.0.0.1])
- by zebra.brightstareng.com (Postfix) with ESMTP
- id 4819F28C004; Fri, 18 May 2007 10:07:49 -0400 (EDT)
-Received: from zebra.brightstareng.com ([127.0.0.1])
- by localhost (zebra [127.0.0.1]) (amavisd-new, port 10024) with ESMTP
- id 05328-06; Fri, 18 May 2007 10:07:16 -0400 (EDT)
-Received: from pippin (unknown [192.168.1.25])
- by zebra.brightstareng.com (Postfix) with ESMTP
- id 8BEF528C1BC; Fri, 18 May 2007 10:06:53 -0400 (EDT)
-From: Ian McDonnell <ian@brightstareng.com>
-To: David Goodenough <david.goodenough@linkchoose.co.uk>
-Subject: Re: something tested this time -- yaffs_mtdif1-compat.c
-Date: Fri, 18 May 2007 10:06:49 -0400
-User-Agent: KMail/1.9.1
-References: <200705142207.06909.ian@brightstareng.com> <200705171131.53536.ian@brightstareng.com> <200705181334.32166.david.goodenough@linkchoose.co.uk>
-In-Reply-To: <200705181334.32166.david.goodenough@linkchoose.co.uk>
-Cc: Andrea Conti <alyf@alyf.net>,
- Charles Manning <manningc2@actrix.gen.nz>
-MIME-Version: 1.0
-Content-Type: Multipart/Mixed;
- boundary="Boundary-00=_5LbTGmt62YoutxM"
-Message-Id: <200705181006.49860.ian@brightstareng.com>
-X-Virus-Scanned: by amavisd-new at brightstareng.com
-Status: R
-X-Status: NT
-X-KMail-EncryptionState:
-X-KMail-SignatureState:
-X-KMail-MDN-Sent:
-
---Boundary-00=_5LbTGmt62YoutxM
-Content-Type: text/plain;
- charset="iso-8859-15"
-Content-Transfer-Encoding: 7bit
-Content-Disposition: inline
-
-David, Andrea,
-
-On Friday 18 May 2007 08:34, you wrote:
-> Yea team. With this fix in place (I put it in the wrong place
-> at first) I can now mount and ls the Yaffs partition without
-> an error messages!
-
-Good news!
-
-Attached is a newer yaffs_mtdif1.c with a bandaid to help the
-2.6.18 and 2.6.19 versions of MTD not trip on the oob read.
-See the LINUX_VERSION_CODE conditional in
-nandmtd1_ReadChunkWithTagsFromNAND.
-
--imcd
-
---Boundary-00=_5LbTGmt62YoutxM
-Content-Type: text/x-csrc;
- charset="iso-8859-15";
- name="yaffs_mtdif1.c"
-Content-Transfer-Encoding: 7bit
-Content-Disposition: attachment;
- filename="yaffs_mtdif1.c"
-
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND.
- *
- * Copyright (C) 2002 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * This module provides the interface between yaffs_nand.c and the
- * MTD API. This version is used when the MTD interface supports the
- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
- * and we have small-page NAND device.
- *
- * These functions are invoked via function pointers in yaffs_nand.c.
- * This replaces functionality provided by functions in yaffs_mtdif.c
- * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are
- * called in yaffs_mtdif.c when the function pointers are NULL.
- * We assume the MTD layer is performing ECC (useNANDECC is true).
- */
-
-#include "yportenv.h"
-#include "yaffs_guts.h"
-#include "yaffs_packedtags1.h"
-#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC
-
-#include "linux/kernel.h"
-#include "linux/version.h"
-#include "linux/types.h"
-#include "linux/mtd/mtd.h"
-
-/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
-
-const char *yaffs_mtdif1_c_version = "$Id$";
-
-#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 <linux/kernel.h>
#include <linux/mm.h>
-#include <linux/sched.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
@@ -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__))