diff options
Diffstat (limited to 'fs/jffs2/gc.c')
-rw-r--r-- | fs/jffs2/gc.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 2d99e06ab223..32ff0373aa04 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,12 @@ 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; + } release_sem: up(&c->alloc_sem); @@ -556,7 +564,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, node = kmalloc(rawlen, GFP_KERNEL); if (!node) - return -ENOMEM; + return -ENOMEM; ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node); if (!ret && retlen != rawlen) @@ -598,10 +606,15 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto bail; } + if (strnlen(node->d.name, node->d.nsize) != node->d.nsize) { + printk(KERN_WARNING "Name in dirent node at 0x%08x contains zeroes\n", ref_offset(raw)); + goto bail; + } + if (node->d.nsize) { crc = crc32(0, node->d.name, node->d.nsize); if (je32_to_cpu(node->d.name_crc) != crc) { - printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent ode at 0x%08x: Read 0x%08x, calculated 0x%08x\n", + printk(KERN_WARNING "Name CRC failed on REF_PRISTINE dirent node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", ref_offset(raw), je32_to_cpu(node->d.name_crc), crc); goto bail; } @@ -624,7 +637,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, if (ret || (retlen != rawlen)) { printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", - rawlen, phys_ofs, ret, retlen); + rawlen, phys_ofs, ret, retlen); if (retlen) { jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL); } else { |