[JFFS2] Fix summary handling of unknown but compatible nodes.
authorDavid Woodhouse <dwmw2@infradead.org>
Sun, 21 May 2006 02:45:27 +0000 (03:45 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Sun, 21 May 2006 02:45:27 +0000 (03:45 +0100)
For RWCOMPAT and ROCOMPAT nodes, we should still allow the mount to
succeed. Just abandon the summary and fall through to the full scan.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
fs/jffs2/erase.c
fs/jffs2/nodelist.h
fs/jffs2/summary.c

index fecf558..f677d69 100644 (file)
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct erase_info *);
 #endif
 static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
-static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
 static void jffs2_erase_block(struct jffs2_sb_info *c,
@@ -283,7 +282,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
                jffs2_del_ino_cache(c, ic);
 }
 
-static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
        struct jffs2_raw_node_ref *ref;
        D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
index 1f5d5b0..194cff7 100644 (file)
@@ -436,6 +436,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c);
 
 /* erase.c */
 void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
+void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 /* wbuf.c */
index 53a84b4..9ced3aa 100644 (file)
@@ -554,9 +554,21 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras
                        }
 #endif
                        default : {
-printk("nodetype = %#04x\n",je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype));
-                               JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
-                               return -EIO;
+                               uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
+                               JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
+                               if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
+                                       return -EIO;
+
+                               /* For compatible node types, just fall back to the full scan */
+                               c->wasted_size -= jeb->wasted_size;
+                               c->free_size += c->sector_size - jeb->free_size;
+                               c->used_size -= jeb->used_size;
+                               c->dirty_size -= jeb->dirty_size;
+                               jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
+                               jeb->free_size = c->sector_size;
+
+                               jffs2_free_all_node_refs(c, jeb);
+                               return -ENOTRECOVERABLE;
                        }
                }
        }
@@ -642,8 +654,12 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
        }
 
        ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
+       /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
+          scan of this eraseblock. So return zero */
+       if (ret == -ENOTRECOVERABLE)
+               return 0;
        if (ret)
-               return ret;
+               return ret;             /* real error */
 
        /* for PARANOIA_CHECK */
        cache_ref = jffs2_alloc_raw_node_ref();