Commit 2665ea84 authored by David Woodhouse's avatar David Woodhouse

[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: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 85becc53
...@@ -122,6 +122,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ...@@ -122,6 +122,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
struct jffs2_inode_cache *ic; struct jffs2_inode_cache *ic;
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *raw; struct jffs2_raw_node_ref *raw;
uint32_t gcblock_dirty;
int ret = 0, inum, nlink; int ret = 0, inum, nlink;
int xattr = 0; int xattr = 0;
...@@ -236,6 +237,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ...@@ -236,6 +237,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
} }
raw = jeb->gc_node; raw = jeb->gc_node;
gcblock_dirty = jeb->dirty_size;
while(ref_obsolete(raw)) { while(ref_obsolete(raw)) {
D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(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) ...@@ -282,7 +284,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
} else { } else {
ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw); ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
} }
goto release_sem; goto test_gcnode;
} }
#endif #endif
...@@ -376,7 +378,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ...@@ -376,7 +378,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
if (ret != -EBADFD) { if (ret != -EBADFD) {
spin_unlock(&c->inocache_lock); spin_unlock(&c->inocache_lock);
goto release_sem; goto test_gcnode;
} }
/* Fall through if it wanted us to, with inocache_lock held */ /* 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) ...@@ -407,6 +409,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
jffs2_gc_release_inode(c, f); 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: release_sem:
up(&c->alloc_sem); up(&c->alloc_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment