summaryrefslogtreecommitdiffstats
path: root/fs/jffs2/gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/gc.c')
-rw-r--r--fs/jffs2/gc.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 967fb2cf8e21..4ea1b7f0ae78 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -125,6 +125,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *raw;
int ret = 0, inum, nlink;
+ int xattr = 0;
if (down_interruptible(&c->alloc_sem))
return -EINTR;
@@ -138,7 +139,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
the node CRCs etc. Do it now. */
/* checked_ino is protected by the alloc_sem */
- if (c->checked_ino > c->highest_ino) {
+ if (c->checked_ino > c->highest_ino && xattr) {
printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n",
c->unchecked_size);
jffs2_dbg_dump_block_lists_nolock(c);
@@ -148,6 +149,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
spin_unlock(&c->erase_completion_lock);
+ if (!xattr)
+ xattr = jffs2_verify_xattr(c);
+
spin_lock(&c->inocache_lock);
ic = jffs2_get_ino_cache(c, c->checked_ino++);
@@ -262,6 +266,16 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
ic = jffs2_raw_ref_to_ic(raw);
+ /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr.
+ We can decide whether this node is inode or xattr by ic->class.
+ ret = 0 : ic is xattr_datum/xattr_ref, and GC was SUCCESSED.
+ ret < 0 : ic is xattr_datum/xattr_ref, but GC was FAILED.
+ ret > 0 : ic is NOT xattr_datum/xattr_ref.
+ */
+ ret = jffs2_garbage_collect_xattr(c, ic);
+ if (ret <= 0)
+ goto release_sem;
+
/* We need to hold the inocache. Either the erase_completion_lock or
the inocache_lock are sufficient; we trade down since the inocache_lock
causes less contention. */