[JFFS2] Fix summary handling of unknown but compatible nodes.

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Sun May 21 14:59:10 EDT 2006


Commit:     7807ef7ba2a41c05f6197381f572dd38baa6c1ce
Parent:     3560160aa26ebced1944aaa2e7e436d2a1b1bf70
Author:     David Woodhouse <dwmw2 at infradead.org>
AuthorDate: Sun May 21 03:45:27 2006 +0100
Commit:     David Woodhouse <dwmw2 at infradead.org>
CommitDate: Sun May 21 03:45:27 2006 +0100

    [JFFS2] Fix summary handling of unknown but compatible nodes.
    
    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 at infradead.org>

 fs/jffs2/erase.c    |    3 +--
 fs/jffs2/nodelist.h |    1 +
 fs/jffs2/summary.c  |   24 ++++++++++++++++++++----
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index fecf558..f677d69 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct 
 #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_ref
 		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));
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 1f5d5b0..194cff7 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -436,6 +436,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_in
 
 /* 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 */
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 53a84b4..9ced3aa 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -554,9 +554,21 @@ #ifdef CONFIG_JFFS2_FS_XATTR
 			}
 #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_
 	}
 
 	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();



More information about the linux-mtd-cvs mailing list