aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/nodelist.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r--fs/jffs2/nodelist.c93
1 files changed, 47 insertions, 46 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 0e82979c741c..5d36e9b4d7c5 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -954,18 +954,16 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
954 for (i=0; i<c->nr_blocks; i++) { 954 for (i=0; i<c->nr_blocks; i++) {
955 this = c->blocks[i].first_node; 955 this = c->blocks[i].first_node;
956 while (this) { 956 while (this) {
957 next = this->next_phys; 957 if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
958 __jffs2_free_raw_node_ref(this); 958 next = this[REFS_PER_BLOCK].next_in_ino;
959 else
960 next = NULL;
961
962 jffs2_free_refblock(this);
959 this = next; 963 this = next;
960 } 964 }
961 c->blocks[i].first_node = c->blocks[i].last_node = NULL; 965 c->blocks[i].first_node = c->blocks[i].last_node = NULL;
962 } 966 }
963 this = c->refs;
964 while (this) {
965 next = this->next_in_ino;
966 __jffs2_free_raw_node_ref(this);
967 this = next;
968 }
969} 967}
970 968
971struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) 969struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset)
@@ -1060,32 +1058,37 @@ struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
1060{ 1058{
1061 struct jffs2_raw_node_ref *ref; 1059 struct jffs2_raw_node_ref *ref;
1062 1060
1063 /* These will be preallocated _very_ shortly. */ 1061 BUG_ON(!jeb->allocated_refs);
1064 ref = c->refs; 1062 jeb->allocated_refs--;
1065 if (!c->refs) { 1063
1066 JFFS2_WARNING("Using non-preallocated refs!\n"); 1064 ref = jeb->last_node;
1067 ref = __jffs2_alloc_raw_node_ref(); 1065
1068 BUG_ON(!ref); 1066 dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
1069 WARN_ON(1); 1067 ref->next_in_ino);
1070 } else { 1068
1071 c->refs = ref->next_in_ino; 1069 while (ref->flash_offset != REF_EMPTY_NODE) {
1070 if (ref->flash_offset == REF_LINK_NODE)
1071 ref = ref->next_in_ino;
1072 else
1073 ref++;
1072 } 1074 }
1073 1075
1074 ref->next_phys = NULL; 1076 dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref,
1077 ref->flash_offset, ofs, ref->next_in_ino, len);
1078
1075 ref->flash_offset = ofs; 1079 ref->flash_offset = ofs;
1076 1080
1077 if (!jeb->first_node) 1081 if (!jeb->first_node) {
1078 jeb->first_node = ref; 1082 jeb->first_node = ref;
1079 if (jeb->last_node) { 1083 BUG_ON(ref_offset(ref) != jeb->offset);
1080 jeb->last_node->next_phys = ref; 1084 } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
1081#ifdef TEST_TOTLEN 1085 uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
1082 if (ref_offset(jeb->last_node) + jeb->last_node->__totlen != ref_offset(ref)) { 1086
1083 printk(KERN_CRIT "Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n", 1087 JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
1084 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, 1088 ref, ref_offset(ref), ref_offset(ref)+len,
1085 ref_offset(jeb->last_node), ref_offset(jeb->last_node)+jeb->last_node->__totlen); 1089 ref_offset(jeb->last_node),
1086 WARN_ON(1); 1090 ref_offset(jeb->last_node)+last_len);
1087 } 1091 BUG();
1088#endif
1089 } 1092 }
1090 jeb->last_node = ref; 1093 jeb->last_node = ref;
1091 1094
@@ -1130,12 +1133,13 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
1130{ 1133{
1131 if (!size) 1134 if (!size)
1132 return 0; 1135 return 0;
1133 if (size > c->sector_size - jeb->used_size) { 1136 if (unlikely(size > jeb->free_size)) {
1134 printk(KERN_CRIT "Dirty space 0x%x larger then used_size 0x%x (wasted 0x%x)\n", 1137 printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
1135 size, jeb->used_size, jeb->wasted_size); 1138 size, jeb->free_size, jeb->wasted_size);
1136 BUG(); 1139 BUG();
1137 } 1140 }
1138 if (jeb->last_node && ref_obsolete(jeb->last_node)) { 1141 /* REF_EMPTY_NODE is !obsolete, so that works OK */
1142 if (ref_obsolete(jeb->last_node)) {
1139#ifdef TEST_TOTLEN 1143#ifdef TEST_TOTLEN
1140 jeb->last_node->__totlen += size; 1144 jeb->last_node->__totlen += size;
1141#endif 1145#endif
@@ -1168,7 +1172,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
1168 jeb = &c->blocks[ref->flash_offset / c->sector_size]; 1172 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1169 1173
1170 /* Last node in block. Use free_space */ 1174 /* Last node in block. Use free_space */
1171 if (ref != jeb->last_node) { 1175 if (unlikely(ref != jeb->last_node)) {
1172 printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n", 1176 printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
1173 ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0); 1177 ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
1174 BUG(); 1178 BUG();
@@ -1183,17 +1187,13 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
1183{ 1187{
1184 uint32_t ret; 1188 uint32_t ret;
1185 1189
1186#if CONFIG_JFFS2_FS_DEBUG > 0
1187 if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
1188 printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
1189 jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
1190 BUG();
1191 }
1192#endif
1193
1194 ret = __ref_totlen(c, jeb, ref); 1190 ret = __ref_totlen(c, jeb, ref);
1191
1195#ifdef TEST_TOTLEN 1192#ifdef TEST_TOTLEN
1196 if (ret != ref->__totlen) { 1193 if (unlikely(ret != ref->__totlen)) {
1194 if (!jeb)
1195 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1196
1197 printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", 1197 printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
1198 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, 1198 ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
1199 ret, ref->__totlen); 1199 ret, ref->__totlen);
@@ -1204,13 +1204,14 @@ uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
1204 printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node); 1204 printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);
1205 1205
1206 printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size); 1206 printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
1207 ret = ref->__totlen; 1207
1208 if (!jeb)
1209 jeb = &c->blocks[ref->flash_offset / c->sector_size];
1210#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) 1208#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
1211 __jffs2_dbg_dump_node_refs_nolock(c, jeb); 1209 __jffs2_dbg_dump_node_refs_nolock(c, jeb);
1212#endif 1210#endif
1211
1213 WARN_ON(1); 1212 WARN_ON(1);
1213
1214 ret = ref->__totlen;
1214 } 1215 }
1215#endif /* TEST_TOTLEN */ 1216#endif /* TEST_TOTLEN */
1216 return ret; 1217 return ret;