|
@@ -256,10 +256,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
|
|
|
|
|
|
if (!raw->next_in_ino) {
|
|
|
/* Inode-less node. Clean marker, snapshot or something like that */
|
|
|
- /* FIXME: If it's something that needs to be copied, including something
|
|
|
- we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */
|
|
|
spin_unlock(&c->erase_completion_lock);
|
|
|
- jffs2_mark_node_obsolete(c, raw);
|
|
|
+ if (ref_flags(raw) == REF_PRISTINE) {
|
|
|
+ /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */
|
|
|
+ jffs2_garbage_collect_pristine(c, NULL, raw);
|
|
|
+ } else {
|
|
|
+ /* Just mark it obsolete */
|
|
|
+ jffs2_mark_node_obsolete(c, raw);
|
|
|
+ }
|
|
|
up(&c->alloc_sem);
|
|
|
goto eraseit_lock;
|
|
|
}
|
|
@@ -533,15 +537,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
|
|
|
|
|
|
D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
|
|
|
|
|
|
- rawlen = ref_totlen(c, c->gcblock, raw);
|
|
|
+ alloclen = rawlen = ref_totlen(c, c->gcblock, raw);
|
|
|
|
|
|
/* Ask for a small amount of space (or the totlen if smaller) because we
|
|
|
don't want to force wastage of the end of a block if splitting would
|
|
|
work. */
|
|
|
- ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) +
|
|
|
- JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen);
|
|
|
- /* this is not the exact summary size of it,
|
|
|
- it is only an upper estimation */
|
|
|
+ if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
|
|
|
+ alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN;
|
|
|
+
|
|
|
+ ret = jffs2_reserve_space_gc(c, alloclen, &phys_ofs, &alloclen, rawlen);
|
|
|
+ /* 'rawlen' is not the exact summary size; it is only an upper estimation */
|
|
|
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -605,9 +610,12 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
- printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
|
|
|
- ref_offset(raw), je16_to_cpu(node->u.nodetype));
|
|
|
- goto bail;
|
|
|
+ /* If it's inode-less, we don't _know_ what it is. Just copy it intact */
|
|
|
+ if (ic) {
|
|
|
+ printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
|
|
|
+ ref_offset(raw), je16_to_cpu(node->u.nodetype));
|
|
|
+ goto bail;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
nraw = jffs2_alloc_raw_node_ref();
|
|
@@ -674,15 +682,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
|
|
|
nraw->flash_offset |= REF_PRISTINE;
|
|
|
jffs2_add_physical_node_ref(c, nraw);
|
|
|
|
|
|
- /* Link into per-inode list. This is safe because of the ic
|
|
|
- state being INO_STATE_GC. Note that if we're doing this
|
|
|
- for an inode which is in-core, the 'nraw' pointer is then
|
|
|
- going to be fetched from ic->nodes by our caller. */
|
|
|
- spin_lock(&c->erase_completion_lock);
|
|
|
- nraw->next_in_ino = ic->nodes;
|
|
|
- ic->nodes = nraw;
|
|
|
- spin_unlock(&c->erase_completion_lock);
|
|
|
-
|
|
|
+ if (ic) {
|
|
|
+ /* Link into per-inode list. This is safe because of the ic
|
|
|
+ state being INO_STATE_GC. Note that if we're doing this
|
|
|
+ for an inode which is in-core, the 'nraw' pointer is then
|
|
|
+ going to be fetched from ic->nodes by our caller. */
|
|
|
+ spin_lock(&c->erase_completion_lock);
|
|
|
+ nraw->next_in_ino = ic->nodes;
|
|
|
+ ic->nodes = nraw;
|
|
|
+ spin_unlock(&c->erase_completion_lock);
|
|
|
+ }
|
|
|
jffs2_mark_node_obsolete(c, raw);
|
|
|
D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
|
|
|
|