diff options
Diffstat (limited to 'fs/jffs2/gc.c')
-rw-r--r-- | fs/jffs2/gc.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 77d30707de56..23587f8a221f 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) | |||
125 | struct jffs2_eraseblock *jeb; | 125 | struct jffs2_eraseblock *jeb; |
126 | struct jffs2_raw_node_ref *raw; | 126 | struct jffs2_raw_node_ref *raw; |
127 | int ret = 0, inum, nlink; | 127 | int ret = 0, inum, nlink; |
128 | int xattr = 0; | ||
128 | 129 | ||
129 | if (down_interruptible(&c->alloc_sem)) | 130 | if (down_interruptible(&c->alloc_sem)) |
130 | return -EINTR; | 131 | return -EINTR; |
@@ -138,7 +139,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
138 | the node CRCs etc. Do it now. */ | 139 | the node CRCs etc. Do it now. */ |
139 | 140 | ||
140 | /* checked_ino is protected by the alloc_sem */ | 141 | /* checked_ino is protected by the alloc_sem */ |
141 | if (c->checked_ino > c->highest_ino) { | 142 | if (c->checked_ino > c->highest_ino && xattr) { |
142 | printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", | 143 | printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", |
143 | c->unchecked_size); | 144 | c->unchecked_size); |
144 | jffs2_dbg_dump_block_lists_nolock(c); | 145 | jffs2_dbg_dump_block_lists_nolock(c); |
@@ -148,6 +149,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
148 | 149 | ||
149 | spin_unlock(&c->erase_completion_lock); | 150 | spin_unlock(&c->erase_completion_lock); |
150 | 151 | ||
152 | if (!xattr) | ||
153 | xattr = jffs2_verify_xattr(c); | ||
154 | |||
151 | spin_lock(&c->inocache_lock); | 155 | spin_lock(&c->inocache_lock); |
152 | 156 | ||
153 | ic = jffs2_get_ino_cache(c, c->checked_ino++); | 157 | ic = jffs2_get_ino_cache(c, c->checked_ino++); |
@@ -262,6 +266,23 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
262 | 266 | ||
263 | ic = jffs2_raw_ref_to_ic(raw); | 267 | ic = jffs2_raw_ref_to_ic(raw); |
264 | 268 | ||
269 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
270 | /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. | ||
271 | * We can decide whether this node is inode or xattr by ic->class. */ | ||
272 | if (ic->class == RAWNODE_CLASS_XATTR_DATUM | ||
273 | || ic->class == RAWNODE_CLASS_XATTR_REF) { | ||
274 | BUG_ON(raw->next_in_ino != (void *)ic); | ||
275 | spin_unlock(&c->erase_completion_lock); | ||
276 | |||
277 | if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { | ||
278 | ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); | ||
279 | } else { | ||
280 | ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); | ||
281 | } | ||
282 | goto release_sem; | ||
283 | } | ||
284 | #endif | ||
285 | |||
265 | /* We need to hold the inocache. Either the erase_completion_lock or | 286 | /* We need to hold the inocache. Either the erase_completion_lock or |
266 | the inocache_lock are sufficient; we trade down since the inocache_lock | 287 | the inocache_lock are sufficient; we trade down since the inocache_lock |
267 | causes less contention. */ | 288 | causes less contention. */ |