aboutsummaryrefslogtreecommitdiff
path: root/fs/jffs2/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/gc.c')
-rw-r--r--fs/jffs2/gc.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 2d99e06ab22..32ff0373aa0 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 {