[JFFS2] Check whether garbage-collection actually obsoleted its victim.

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Sat Oct 13 06:59:01 EDT 2007


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=2665ea842dc9f4c04bdb57f8b7c2023759ac8c85
Commit:     2665ea842dc9f4c04bdb57f8b7c2023759ac8c85
Parent:     85becc535b7f33be5aefdb8ecea9fac4998e4b6f
Author:     David Woodhouse <dwmw2 at infradead.org>
AuthorDate: Sat Oct 13 11:31:23 2007 +0100
Committer:  David Woodhouse <dwmw2 at infradead.org>
CommitDate: Sat Oct 13 11:31:23 2007 +0100

    [JFFS2] Check whether garbage-collection actually obsoleted its victim.
    
    In OLPC trac #4184 we found a case where a corrupted node didn't
    actually get obsoleted when we tried to garbage-collect it. So we wrote
    out many million copies of it, in repeated attempts to obsolete it,
    until the flash became full. Don't Do That.
    
    Signed-off-by: David Woodhouse <dwmw2 at infradead.org>
---
 fs/jffs2/gc.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index eded819..95be264 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -122,6 +122,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 	struct jffs2_inode_cache *ic;
 	struct jffs2_eraseblock *jeb;
 	struct jffs2_raw_node_ref *raw;
+	uint32_t gcblock_dirty;
 	int ret = 0, inum, nlink;
 	int xattr = 0;
 
@@ -236,6 +237,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 	}
 
 	raw = jeb->gc_node;
+	gcblock_dirty = jeb->dirty_size;
 
 	while(ref_obsolete(raw)) {
 		D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw)));
@@ -282,7 +284,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 		} else {
 			ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
 		}
-		goto release_sem;
+		goto test_gcnode;
 	}
 #endif
 
@@ -376,7 +378,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 
 		if (ret != -EBADFD) {
 			spin_unlock(&c->inocache_lock);
-			goto release_sem;
+			goto test_gcnode;
 		}
 
 		/* Fall through if it wanted us to, with inocache_lock held */
@@ -407,6 +409,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 
 	jffs2_gc_release_inode(c, f);
 
+ test_gcnode:
+	if (jeb->dirty_size == gcblock_dirty && !ref_obsolete(jeb->gc_node)) {
+		/* Eep. This really should never happen. GC is broken */
+		printk(KERN_ERR "Error garbage collecting node at %08x!\n", ref_offset(jeb->gc_node));
+		ret = -ENOSPC;
+	} else if (ref_offset(jeb->gc_node) == 0x1c616bdc)
+		printk(KERN_ERR "Wheee. Correctly GC'd node at %08x\n", ref_offset(jeb->gc_node));
+
  release_sem:
 	up(&c->alloc_sem);
 



More information about the linux-mtd-cvs mailing list