JFFS2 OOPS in 2.6.20
Joakim Tjernlund
joakim.tjernlund at transmode.se
Fri Mar 9 06:15:08 EST 2007
On Fri, 2007-03-09 at 11:46 +0100, Joakim Tjernlund wrote:
> On Fri, 2007-03-09 at 09:23 +0000, David Woodhouse wrote:
> > On Fri, 2007-03-09 at 10:02 +0100, Joakim Tjernlund wrote:
> > > JFFS2 notice: (137) read_unknown: ref_flags(ref) == REF_UNCHECKED at 0x3aa6c6c.
> > > {0000,0000,00000000,00000000}
> >
> > Ouch. That CRC is actually "correct". It's why we should have used
> > crc32(-1, buf, len) instead of crc32(0, buf, len) from the start.
> >
> > Do you have any idea how you managed to get those zeroes on the flash?
>
> Not much, our system test did power cycle testing while doing SW
> upgrade(lots of writing of files).
>
> Tested your patch and now it boots again with this :)
> JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa87a0.
> {0040,4001,00000044,00000000}
> JFFS2 error: (137) read_unknown: REF_UNCHECKED but unknown node at 0x3aa6c6c
> JFFS2 error: (137) read_unknown: Node is {0000,0000,00000000,00000000}. Please report this error.
> JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa517c.
> {0400,4001,00000000,00000004}
> JFFS2 error: (137) read_unknown: REF_UNCHECKED but unknown node at 0x3aa28fc
> JFFS2 error: (137) read_unknown: Node is {0000,0000,00000000,00000000}. Please report this error.
> JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa1ef8.
> {0000,0000,00000000,00100400}
> JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa1438.
> {0000,4000,00000000,00000000}
> JFFS2 error: (137) read_unknown: REF_UNCHECKED but unknown node at 0x3aa0a44
> JFFS2 error: (137) read_unknown: Node is {0000,0000,00000000,00000000}. Please report this error.
> JFFS2 error: (137) read_unknown: REF_UNCHECKED but unknown node at 0x3aa3e84
> JFFS2 error: (137) read_unknown: Node is {0000,0000,00000000,00000000}. Please report this error.
> JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa3d80.
> {0040,4000,00000000,01000005}
> JFFS2 error: (137) read_unknown: REF_UNCHECKED but unknown node at 0x3aa33c8
> JFFS2 error: (137) read_unknown: Node is {0000,0000,00000000,00000000}. Please report this error.
> VFS: Mounted root (jffs2 filesystem).
This does not look right, none of the "All zero node header" checks has triggered.
hmm,
je32_to_cpu(node->u.totlen) should be !je32_to_cpu(node->u.totlen)
also I think this check should be before the real crc32 check.
After that I get:
JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa87a0.
{0040,4001,00000044,00000000}
JFFS2 notice: (137) jffs2_get_inode_nodes: All zero node header at 0x3aa6c6c.
JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa517c.
{0400,4001,00000000,00000004}
JFFS2 notice: (137) jffs2_get_inode_nodes: All zero node header at 0x3aa28fc.
JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa1ef8.
{0000,0000,00000000,00100400}
JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa1438.
{0000,4000,00000000,00000000}
JFFS2 notice: (137) jffs2_get_inode_nodes: All zero node header at 0x3aa0a44.
JFFS2 notice: (137) jffs2_get_inode_nodes: All zero node header at 0x3aa3e84.
JFFS2 notice: (137) jffs2_get_inode_nodes: Node header CRC failed at 0x3aa3d80.
{0040,4000,00000000,01000005}
JFFS2 notice: (137) jffs2_get_inode_nodes: All zero node header at 0x3aa33c8.
VFS: Mounted root (jffs2 filesystem).
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 58a0b91..7f7618c 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -373,7 +373,14 @@ free_out:
static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
{
/* We don't mark unknown nodes as REF_UNCHECKED */
- BUG_ON(ref_flags(ref) == REF_UNCHECKED);
+ if (ref_flags(ref) == REF_UNCHECKED) {
+ JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
+ ref_offset(ref));
+ JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
+ je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
+ je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
+ return 1;
+ }
un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
@@ -565,6 +572,14 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
node = (union jffs2_node_union *)bufstart;
+ /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
+ if (!je32_to_cpu(node->u.hdr_crc) && !je16_to_cpu(node->u.nodetype) &&
+ !je16_to_cpu(node->u.magic) && !je32_to_cpu(node->u.totlen)) {
+ JFFS2_NOTICE("All zero node header at %#08x.\n", ref_offset(ref));
+ jffs2_mark_node_obsolete(c, ref);
+ goto cont;
+ }
+
/* No need to mask in the valid bit; it shouldn't be invalid */
if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 3af746e..b98661a 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -718,6 +718,17 @@ scan_more:
crcnode.totlen = node->totlen;
hdr_crc = crc32(0, &crcnode, sizeof(crcnode)-4);
+ /* Due to poor choice of crc32 seed, an all-zero node will have a correct CRC */
+ if (!je32_to_cpu(node->hdr_crc) && !je16_to_cpu(node->nodetype) &&
+ !je16_to_cpu(node->magic) && !je32_to_cpu(node->totlen)) {
+ noisy_printk(&noise, "jffs2_scan_eraseblock(): All zero node header at 0x%08x.\n", ofs);
+
+ if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+ return err;
+ ofs += 4;
+ continue;
+ }
+
if (hdr_crc != je32_to_cpu(node->hdr_crc)) {
noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n",
ofs, je16_to_cpu(node->magic),
More information about the linux-mtd
mailing list