Skip to content

Commit

Permalink
[JFFS2] Correct handling of JFFS2_FEATURE_RWCOMPAT_COPY nodes.
Browse files Browse the repository at this point in the history
We should preserve these when we come to garbage collect them, not let
them get erased. Use jffs2_garbage_collect_pristine() for this, and make
sure the summary code copes -- just refrain from writing a summary for any
block which contains a node we don't understand.

Signed-off-by: David Woodhouse <dwmw2@infradead.org>
  • Loading branch information
David Woodhouse committed May 20, 2006
1 parent fb9fbbc commit 6171586
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 23 deletions.
49 changes: 29 additions & 20 deletions fs/jffs2/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)));

Expand Down
5 changes: 5 additions & 0 deletions fs/jffs2/nodelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ struct jffs2_raw_node_ref
#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE)
#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)

/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
copied. If you need to do anything different to GC inode-less nodes, then
you need to modify gc.c accordingly. */

/* For each inode in the filesystem, we need to keep a record of
nlink, because it would be a PITA to scan the whole directory tree
at read_inode() time to calculate it, and to keep sufficient information
Expand Down
15 changes: 13 additions & 2 deletions fs/jffs2/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,11 +851,22 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
ofs += PAD(je32_to_cpu(node->totlen));
break;

case JFFS2_FEATURE_RWCOMPAT_COPY:
case JFFS2_FEATURE_RWCOMPAT_COPY: {
struct jffs2_raw_node_ref *ref;
D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
USED_SPACE(PAD(je32_to_cpu(node->totlen)));

ref = jffs2_alloc_raw_node_ref();
if (!ref)
return -ENOMEM;
ref->flash_offset = ofs | REF_PRISTINE;
ref->next_in_ino = 0;
jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)));

/* We can't summarise nodes we don't grok */
jffs2_sum_disable_collecting(s);
ofs += PAD(je32_to_cpu(node->totlen));
break;
}
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion fs/jffs2/summary.c
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,14 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
}
#endif
default : {
BUG(); /* unknown node in summary information */
if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
== JFFS2_FEATURE_RWCOMPAT_COPY) {
dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
je16_to_cpu(temp->u.nodetype));
jffs2_sum_disable_collecting(c->summary);
} else {
BUG(); /* unknown node in summary information */
}
}
}

Expand Down

0 comments on commit 6171586

Please sign in to comment.