[PATCH] JFFS2 kernel panics fixup on Sibley

Alexey, Korolev alexey.korolev at intel.com
Tue Dec 27 08:07:41 EST 2005


Hi all,
 
We faced kernel panics on platforms with Sibley NOR chip. It is mostly 
concerned with introducing EBH in JFFS2 code.
We made some fixes for it:
Size of EBH is configured incorrectly for chips with programming 
regions. It should be equal page size. Write buffer offsets and lens 
should be page aligned.
There are several misprints in jffs2_scan_eraseblock() function with 
jffs2_flash_read_safe offsets.
Also there is incorrect OOB buffer assignment and EBH CRC check in 
jffs2_check_cleanmarker_ebh(), patch fixes mounting issues of JFFS2 we 
found on NAND devices.
 
Please find diff file below.
 
Thanks,
Alexey Korolev, Alexander Belyakov

======================================= 
 
diff -aur c/fs/jffs2/erase.c b/fs/jffs2/erase.c
--- c/fs/jffs2/erase.c 2005-12-23 16:43:09.000000000 +0300
+++ b/fs/jffs2/erase.c 2005-12-23 16:48:43.000000000 +0300
@@ -391,7 +391,7 @@
   struct jffs2_raw_ebh ebh = {
    .magic =        cpu_to_je16(JFFS2_MAGIC_BITMASK),
    .nodetype =     cpu_to_je16(JFFS2_NODETYPE_ERASEBLOCK_HEADER),
-   .totlen =       cpu_to_je32(sizeof(struct jffs2_raw_ebh)),
+   .totlen =       cpu_to_je32(c->ebh_size),
    .reserved =     0,
    .compat_fset =  JFFS2_EBH_COMPAT_FSET,
    .incompat_fset = JFFS2_EBH_INCOMPAT_FSET,
diff -aur c/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
--- c/fs/jffs2/nodelist.c 2005-12-23 16:43:09.000000000 +0300
+++ b/fs/jffs2/nodelist.c 2005-12-23 16:48:43.000000000 +0300
@@ -436,7 +436,7 @@
   * adding and jffs2_flash_read_end() interface. */
  if (c->mtd->point) {
   err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
-  if (!err && retlen < tn->csize) {
+  if (!err && retlen < len) {
    JFFS2_WARNING("MTD point returned len too short: %u instead of 
%u.\n", retlen, tn->csize);
    c->mtd->unpoint(c->mtd, buffer, ofs, len);
   } else if (err)
diff -aur c/fs/jffs2/scan.c b/fs/jffs2/scan.c
--- c/fs/jffs2/scan.c 2005-12-23 16:43:09.000000000 +0300
+++ b/fs/jffs2/scan.c 2005-12-23 16:48:43.000000000 +0300
@@ -454,7 +454,7 @@
    buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
    D1(printk(KERN_DEBUG "Fewer than %zd bytes (node header) left to end 
of buf. Reading 0x%x at 0x%08x\n",
       sizeof(struct jffs2_unknown_node), buf_len, ofs));
-   err = jffs2_flash_read_safe(c, buf_ofs, buf_len, buf);
+   err = jffs2_flash_read_safe(c, ofs, buf_len, buf);
    if (err)
     return err;
    buf_ofs = ofs;
@@ -511,7 +511,7 @@
     break;
    }
    D1(printk(KERN_DEBUG "Reading another 0x%x at 0x%08x\n", buf_len, ofs));
-   err = jffs2_flash_read_safe(c, buf_ofs, buf_len, buf);
+   err = jffs2_flash_read_safe(c, ofs, buf_len, buf);
    if (err)
     return err;
    buf_ofs = ofs;
@@ -587,7 +587,7 @@
     buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - 
ofs);
     D1(printk(KERN_DEBUG "Fewer than %zd bytes (inode node) left to end 
of buf. Reading 0x%x at 0x%08x\n",
        sizeof(struct jffs2_raw_inode), buf_len, ofs));
-    err = jffs2_flash_read_safe(c, buf_ofs, buf_len, buf);
+    err = jffs2_flash_read_safe(c, ofs, buf_len, buf);
     if (err)
      return err;
     buf_ofs = ofs;
@@ -603,7 +603,7 @@
     buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - 
ofs);
     D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end 
of buf. Reading 0x%x at 0x%08x\n",
        je32_to_cpu(node->totlen), buf_len, ofs));
-    err = jffs2_flash_read_safe(c, buf_ofs, buf_len, buf);
+    err = jffs2_flash_read_safe(c, ofs, buf_len, buf);
     if (err)
      return err;
     buf_ofs = ofs;
@@ -650,7 +650,7 @@
    } else {
     if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
      buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - 
ofs);
-     err = jffs2_flash_read_safe(c, buf_ofs, buf_len, buf);
+     err = jffs2_flash_read_safe(c, ofs, buf_len, buf);
      if (err)
       return err;
      buf_ofs = ofs;
diff -aur c/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
--- c/fs/jffs2/wbuf.c 2005-12-23 16:43:09.000000000 +0300
+++ b/fs/jffs2/wbuf.c 2005-12-23 16:57:50.000000000 +0300
@@ -635,7 +635,7 @@
  /* Fixup the wbuf if we are moving to a new eraseblock.  The checks below
     fail for ECC'd NOR because cleanmarker == 16, so a block starts at
     xxx0010.  */
- if (jffs2_nor_ecc(c)) {
+ if (jffs2_nor_ecc(c) || jffs2_nor_wbuf_flash(c)) {
   if (((c->wbuf_ofs % c->sector_size) == 0) && !c->wbuf_len) {
    c->wbuf_ofs = PAGE_DIV(to);
    c->wbuf_len = PAGE_MOD(to);
@@ -997,7 +997,7 @@
  uint32_t oob_nr, total_len;
  unsigned char *buf;
  int ret;
- struct jffs2_unknown_node *n;
+ struct jffs2_unknown_node *n, un;
  struct jffs2_raw_ebh eh;
  uint32_t read_in = 0, i = 0, copy_len, node_crc;
 
@@ -1028,7 +1028,16 @@
   goto out;
  }
 
- n = (struct jffs2_unknown_node *) &buf[c->fsdata_pos];
+ i = 0;
+ read_in = 0;
+ while (read_in < sizeof(struct jffs2_unknown_node)) {
+  copy_len = min_t(uint32_t, c->fsdata_len, sizeof(struct 
jffs2_unknown_node) - read_in);
+  memcpy((unsigned char *)&un + read_in, &buf[oob_size*i + 
c->fsdata_pos], copy_len);
+  read_in += copy_len;
+  i++;
+ }
+ n = &un;
+
  if (je16_to_cpu(n->magic) != JFFS2_MAGIC_BITMASK) {
   D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker_ebh(): 
Cleanmarker node not detected in block at %08x\n", jeb->offset));
   ret = 1;
@@ -1045,6 +1054,8 @@
   goto out;
  }else if (je16_to_cpu(n->nodetype) == JFFS2_NODETYPE_ERASEBLOCK_HEADER) {
   /* Read the scattered data(in buf[]) into struct jffs2_raw_ebh */
+  i = 0;
+  read_in = 0;
   while (read_in < sizeof(struct jffs2_raw_ebh)) {
    copy_len = min_t(uint32_t, c->fsdata_len, sizeof(struct 
jffs2_raw_ebh) - read_in);
    memcpy((unsigned char *)&eh + read_in, &buf[oob_size*i + 
c->fsdata_pos], copy_len);
@@ -1052,7 +1063,7 @@
    i++;
   }
 
-  node_crc = crc32(0, &eh, sizeof(struct jffs2_raw_ebh)-8);
+  node_crc = crc32(0, &eh + sizeof(struct jffs2_unknown_node) + 4, 
sizeof(struct jffs2_raw_ebh) - sizeof(struct jffs2_unknown_node) - 4);
   if (node_crc != je32_to_cpu(eh.node_crc)) {
    ret = 1;
    goto out;




More information about the linux-mtd mailing list