I'm working on upgrading a client's kernel from 2.6.10 to
2.6.22. They are using yaffs to store their configuration
data.
When I start the 2.6.22 kernel, I get a number of the following:
**>> yaffs chunk 32 was not erased
If I run 2.6.10 after writing the files from 2.6.22 I get
blocks with ECC errors in them, and the files get corrupted.
After adding some debug in to yaffs_ECCCorrect, the following
seems to be indicative of the output:
yaffs_ECCCorrect: READ 02,00,10 WANT ff,ff,ff, DIFF fd,ff,ef
I have run a diff of the 2.6.10 source tree's yaffs, and the
summary of the changes is:
fs/yaffs2/yaffs_fs.c 1.61 => 1.63
fs/yaffs2/yaffs_tagscompat.c and yaffs2/yportenv.h seem to have
changed but no change in CVSID.
The 2.6.22 was patches from the CVS at 24th September 2007.
Anyone have any pointers about debugging this problem, or is it
a problem that people have seen before?
The NAND controller is an S3C2412, although it seems that neither
kernel is trying to use the hardware generated ECCs.
Yaffs config:
CONFIG_YAFFS_FS=y
CONFIG_YAFFS_YAFFS1=y
# CONFIG_YAFFS_9BYTE_TAGS is not set
CONFIG_YAFFS_DOES_ECC=y
# CONFIG_YAFFS_ECC_WRONG_ORDER is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
The full diff is here:
diff -urNp /home/ben/customer/src/kernel-P7/linux-2.6.10/fs/yaffs2/yaffs_fs.c fs/yaffs2/yaffs_fs.c
--- /home/ben/customer/src/kernel-P7/linux-2.6.10/fs/yaffs2/yaffs_fs.c 2007-08-31 00:46:13.000000000 +0100
+++ fs/yaffs2/yaffs_fs.c 2007-10-10 21:26:47.000000000 +0100
@@ -32,7 +32,7 @@
*/
const char *yaffs_fs_c_version =
- "$Id: yaffs_fs.c,v 1.61 2007-07-18 19:40:38 charles Exp $";
+ "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $";
extern const char *yaffs_guts_c_version;
#include <linux/version.h>
@@ -213,24 +213,45 @@ static struct address_space_operations y
.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))
.sendfile = generic_file_sendfile,
#endif
-
};
+#endif
static struct inode_operations yaffs_file_inode_operations = {
.setattr = yaffs_setattr,
@@ -1430,6 +1451,7 @@ static void yaffs_read_inode(struct inod
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);
@@ -1458,6 +1480,7 @@ static int yaffs_remount_fs(struct super
return 0;
}
+#endif
static void yaffs_put_super(struct super_block *sb)
{
@@ -2095,7 +2118,7 @@ static int yaffs_proc_write(struct file
unsigned rg = 0, mask_bitfield;
char *end;
char *mask_name;
- char *x;
+ const char *x;
char substring[MAX_MASK_NAME_LENGTH+1];
int i;
int done = 0;
@@ -2128,6 +2151,7 @@ static int yaffs_proc_write(struct file
if (end > buf + pos) {
mask_name = "numeral";
len = end - (buf + pos);
+ pos += len;
done = 0;
} else {
for(x = buf + pos, i = 0;
@@ -2137,8 +2161,6 @@ static int yaffs_proc_write(struct file
substring[i] = '\0';
for (i = 0; mask_flags[i].mask_name != NULL; i++) {
- //len = strlen(mask_flags[i].mask_name);
- //if (strncmp(buf + pos, mask_flags[i].mask_name, len) == 0) {
if(strcmp(substring,mask_flags[i].mask_name) == 0){
mask_name = mask_flags[i].mask_name;
mask_bitfield = mask_flags[i].mask_bitfield;
@@ -2149,7 +2171,6 @@ static int yaffs_proc_write(struct file
}
if (mask_name != NULL) {
- // pos += len;
done = 0;
switch(add) {
case '-':
diff -urNp /home/ben/customer/src/kernel-P7/linux-2.6.10/fs/yaffs2/yaffs_tagscompat.c fs/yaffs2/yaffs_tagscompat.c
--- /home/ben/customer/src/kernel-P7/linux-2.6.10/fs/yaffs2/yaffs_tagscompat.c 2007-08-31 00:46:13.000000000 +0100
+++ fs/yaffs2/yaffs_tagscompat.c 2007-10-10 21:26:47.000000000 +0100
@@ -435,7 +435,7 @@ int yaffs_TagsCompatabilityReadChunkWith
yaffs_Spare spare;
yaffs_Tags tags;
- yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
+ yaffs_ECCResult eccResult;
static yaffs_Spare spareFF;
static int init;
diff -urNp /home/ben/customer/src/kernel-P7/linux-2.6.10/fs/yaffs2/yportenv.h fs/yaffs2/yportenv.h
--- /home/ben/customer/src/kernel-P7/linux-2.6.10/fs/yaffs2/yportenv.h 2007-08-31 00:46:13.000000000 +0100
+++ fs/yaffs2/yportenv.h 2007-10-10 21:26:47.000000000 +0100
@@ -32,6 +32,7 @@
#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>
--
Ben
Q: What's a light-year?
A: One-third less calories than a regular year.