diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-20 19:02:06 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-20 19:02:06 -0400 |
commit | 6171586a7ae5198988774e8480631e8d15f65dfe (patch) | |
tree | eef74bde60005c4e39c0c213030b27cb07a5c236 /fs/jffs2/gc.c | |
parent | fb9fbbcc9389edabb172ac1b6419c01e32046787 (diff) |
[JFFS2] Correct handling of JFFS2_FEATURE_RWCOMPAT_COPY nodes.
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>
Diffstat (limited to 'fs/jffs2/gc.c')
-rw-r--r-- | fs/jffs2/gc.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 23587f8a221f..b0a5c407b476 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -256,10 +256,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
256 | 256 | ||
257 | if (!raw->next_in_ino) { | 257 | if (!raw->next_in_ino) { |
258 | /* Inode-less node. Clean marker, snapshot or something like that */ | 258 | /* Inode-less node. Clean marker, snapshot or something like that */ |
259 | /* FIXME: If it's something that needs to be copied, including something | ||
260 | we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ | ||
261 | spin_unlock(&c->erase_completion_lock); | 259 | spin_unlock(&c->erase_completion_lock); |
262 | jffs2_mark_node_obsolete(c, raw); | 260 | if (ref_flags(raw) == REF_PRISTINE) { |
261 | /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */ | ||
262 | jffs2_garbage_collect_pristine(c, NULL, raw); | ||
263 | } else { | ||
264 | /* Just mark it obsolete */ | ||
265 | jffs2_mark_node_obsolete(c, raw); | ||
266 | } | ||
263 | up(&c->alloc_sem); | 267 | up(&c->alloc_sem); |
264 | goto eraseit_lock; | 268 | goto eraseit_lock; |
265 | } | 269 | } |
@@ -533,15 +537,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
533 | 537 | ||
534 | D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); | 538 | D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); |
535 | 539 | ||
536 | rawlen = ref_totlen(c, c->gcblock, raw); | 540 | alloclen = rawlen = ref_totlen(c, c->gcblock, raw); |
537 | 541 | ||
538 | /* Ask for a small amount of space (or the totlen if smaller) because we | 542 | /* Ask for a small amount of space (or the totlen if smaller) because we |
539 | don't want to force wastage of the end of a block if splitting would | 543 | don't want to force wastage of the end of a block if splitting would |
540 | work. */ | 544 | work. */ |
541 | ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + | 545 | if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) |
542 | JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); | 546 | alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN; |
543 | /* this is not the exact summary size of it, | 547 | |
544 | it is only an upper estimation */ | 548 | ret = jffs2_reserve_space_gc(c, alloclen, &phys_ofs, &alloclen, rawlen); |
549 | /* 'rawlen' is not the exact summary size; it is only an upper estimation */ | ||
545 | 550 | ||
546 | if (ret) | 551 | if (ret) |
547 | return ret; | 552 | return ret; |
@@ -605,9 +610,12 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
605 | } | 610 | } |
606 | break; | 611 | break; |
607 | default: | 612 | default: |
608 | printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", | 613 | /* If it's inode-less, we don't _know_ what it is. Just copy it intact */ |
609 | ref_offset(raw), je16_to_cpu(node->u.nodetype)); | 614 | if (ic) { |
610 | goto bail; | 615 | printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", |
616 | ref_offset(raw), je16_to_cpu(node->u.nodetype)); | ||
617 | goto bail; | ||
618 | } | ||
611 | } | 619 | } |
612 | 620 | ||
613 | nraw = jffs2_alloc_raw_node_ref(); | 621 | nraw = jffs2_alloc_raw_node_ref(); |
@@ -674,15 +682,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
674 | nraw->flash_offset |= REF_PRISTINE; | 682 | nraw->flash_offset |= REF_PRISTINE; |
675 | jffs2_add_physical_node_ref(c, nraw); | 683 | jffs2_add_physical_node_ref(c, nraw); |
676 | 684 | ||
677 | /* Link into per-inode list. This is safe because of the ic | 685 | if (ic) { |
678 | state being INO_STATE_GC. Note that if we're doing this | 686 | /* Link into per-inode list. This is safe because of the ic |
679 | for an inode which is in-core, the 'nraw' pointer is then | 687 | state being INO_STATE_GC. Note that if we're doing this |
680 | going to be fetched from ic->nodes by our caller. */ | 688 | for an inode which is in-core, the 'nraw' pointer is then |
681 | spin_lock(&c->erase_completion_lock); | 689 | going to be fetched from ic->nodes by our caller. */ |
682 | nraw->next_in_ino = ic->nodes; | 690 | spin_lock(&c->erase_completion_lock); |
683 | ic->nodes = nraw; | 691 | nraw->next_in_ino = ic->nodes; |
684 | spin_unlock(&c->erase_completion_lock); | 692 | ic->nodes = nraw; |
685 | 693 | spin_unlock(&c->erase_completion_lock); | |
694 | } | ||
686 | jffs2_mark_node_obsolete(c, raw); | 695 | jffs2_mark_node_obsolete(c, raw); |
687 | D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); | 696 | D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); |
688 | 697 | ||