aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-20 19:02:06 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-20 19:02:06 -0400
commit6171586a7ae5198988774e8480631e8d15f65dfe (patch)
treeeef74bde60005c4e39c0c213030b27cb07a5c236
parentfb9fbbcc9389edabb172ac1b6419c01e32046787 (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>
-rw-r--r--fs/jffs2/gc.c49
-rw-r--r--fs/jffs2/nodelist.h5
-rw-r--r--fs/jffs2/scan.c15
-rw-r--r--fs/jffs2/summary.c9
4 files changed, 55 insertions, 23 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
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index bac4ec35bbd0..1f5d5b0100aa 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -97,6 +97,11 @@ struct jffs2_raw_node_ref
97#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) 97#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE)
98#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) 98#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
99 99
100/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
101 it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
102 copied. If you need to do anything different to GC inode-less nodes, then
103 you need to modify gc.c accordingly. */
104
100/* For each inode in the filesystem, we need to keep a record of 105/* For each inode in the filesystem, we need to keep a record of
101 nlink, because it would be a PITA to scan the whole directory tree 106 nlink, because it would be a PITA to scan the whole directory tree
102 at read_inode() time to calculate it, and to keep sufficient information 107 at read_inode() time to calculate it, and to keep sufficient information
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 3cbe9f029e01..06637050749d 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -851,11 +851,22 @@ scan_more:
851 ofs += PAD(je32_to_cpu(node->totlen)); 851 ofs += PAD(je32_to_cpu(node->totlen));
852 break; 852 break;
853 853
854 case JFFS2_FEATURE_RWCOMPAT_COPY: 854 case JFFS2_FEATURE_RWCOMPAT_COPY: {
855 struct jffs2_raw_node_ref *ref;
855 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); 856 D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
856 USED_SPACE(PAD(je32_to_cpu(node->totlen))); 857
858 ref = jffs2_alloc_raw_node_ref();
859 if (!ref)
860 return -ENOMEM;
861 ref->flash_offset = ofs | REF_PRISTINE;
862 ref->next_in_ino = 0;
863 jffs2_link_node_ref(c, jeb, ref, PAD(je32_to_cpu(node->totlen)));
864
865 /* We can't summarise nodes we don't grok */
866 jffs2_sum_disable_collecting(s);
857 ofs += PAD(je32_to_cpu(node->totlen)); 867 ofs += PAD(je32_to_cpu(node->totlen));
858 break; 868 break;
869 }
859 } 870 }
860 } 871 }
861 } 872 }
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index 95b5bf8f4a99..53a84b468cfe 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -760,7 +760,14 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
760 } 760 }
761#endif 761#endif
762 default : { 762 default : {
763 BUG(); /* unknown node in summary information */ 763 if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
764 == JFFS2_FEATURE_RWCOMPAT_COPY) {
765 dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
766 je16_to_cpu(temp->u.nodetype));
767 jffs2_sum_disable_collecting(c->summary);
768 } else {
769 BUG(); /* unknown node in summary information */
770 }
764 } 771 }
765 } 772 }
766 773