diff options
Diffstat (limited to 'fs/jffs2/nodelist.c')
-rw-r--r-- | fs/jffs2/nodelist.c | 115 |
1 files changed, 108 insertions, 7 deletions
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 00506857eabc..9a6ced05f894 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -1052,8 +1052,17 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | |||
1052 | { | 1052 | { |
1053 | if (!jeb->first_node) | 1053 | if (!jeb->first_node) |
1054 | jeb->first_node = ref; | 1054 | jeb->first_node = ref; |
1055 | if (jeb->last_node) | 1055 | if (jeb->last_node) { |
1056 | jeb->last_node->next_phys = ref; | 1056 | jeb->last_node->next_phys = ref; |
1057 | #ifdef TEST_TOTLEN | ||
1058 | if (ref_offset(jeb->last_node) + jeb->last_node->__totlen != ref_offset(ref)) { | ||
1059 | printk(KERN_CRIT "Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n", | ||
1060 | ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, | ||
1061 | ref_offset(jeb->last_node), ref_offset(jeb->last_node)+jeb->last_node->__totlen); | ||
1062 | WARN_ON(1); | ||
1063 | } | ||
1064 | #endif | ||
1065 | } | ||
1057 | jeb->last_node = ref; | 1066 | jeb->last_node = ref; |
1058 | 1067 | ||
1059 | switch(ref_flags(ref)) { | 1068 | switch(ref_flags(ref)) { |
@@ -1076,18 +1085,110 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | |||
1076 | c->free_size -= len; | 1085 | c->free_size -= len; |
1077 | jeb->free_size -= len; | 1086 | jeb->free_size -= len; |
1078 | 1087 | ||
1079 | /* Set __totlen field... for now */ | ||
1080 | ref->__totlen = len; | ||
1081 | ref->next_phys = NULL; | 1088 | ref->next_phys = NULL; |
1089 | #ifdef TEST_TOTLEN | ||
1090 | /* Set (and test) __totlen field... for now */ | ||
1091 | ref->__totlen = len; | ||
1092 | ref_totlen(c, jeb, ref); | ||
1093 | #endif | ||
1082 | } | 1094 | } |
1083 | 1095 | ||
1096 | /* No locking. Do not use on a live file system */ | ||
1084 | int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 1097 | int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
1085 | uint32_t size) | 1098 | uint32_t size) |
1086 | { | 1099 | { |
1087 | c->dirty_size += size; | 1100 | if (!size) |
1088 | c->free_size -= size; | 1101 | return 0; |
1089 | jeb->dirty_size += size; | 1102 | if (size > c->sector_size - jeb->used_size) { |
1090 | jeb->free_size -= size; | 1103 | printk(KERN_CRIT "Dirty space 0x%x larger then used_size 0x%x (wasted 0x%x)\n", |
1104 | size, jeb->used_size, jeb->wasted_size); | ||
1105 | BUG(); | ||
1106 | } | ||
1107 | if (jeb->last_node && ref_obsolete(jeb->last_node)) { | ||
1108 | #ifdef TEST_TOTLEN | ||
1109 | jeb->last_node->__totlen += size; | ||
1110 | #endif | ||
1111 | c->dirty_size += size; | ||
1112 | c->free_size -= size; | ||
1113 | jeb->dirty_size += size; | ||
1114 | jeb->free_size -= size; | ||
1115 | } else { | ||
1116 | struct jffs2_raw_node_ref *ref; | ||
1117 | ref = jffs2_alloc_raw_node_ref(); | ||
1118 | if (!ref) | ||
1119 | return -ENOMEM; | ||
1120 | |||
1121 | ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size; | ||
1122 | ref->flash_offset |= REF_OBSOLETE; | ||
1123 | ref->next_in_ino = 0; | ||
1124 | #ifdef TEST_TOTLEN | ||
1125 | ref->__totlen = size; | ||
1126 | #endif | ||
1127 | |||
1128 | jffs2_link_node_ref(c, jeb, ref, size); | ||
1129 | } | ||
1091 | 1130 | ||
1092 | return 0; | 1131 | return 0; |
1093 | } | 1132 | } |
1133 | |||
1134 | /* Calculate totlen from surrounding nodes or eraseblock */ | ||
1135 | static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, | ||
1136 | struct jffs2_eraseblock *jeb, | ||
1137 | struct jffs2_raw_node_ref *ref) | ||
1138 | { | ||
1139 | uint32_t ref_end; | ||
1140 | |||
1141 | if (ref->next_phys) | ||
1142 | ref_end = ref_offset(ref->next_phys); | ||
1143 | else { | ||
1144 | if (!jeb) | ||
1145 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
1146 | |||
1147 | /* Last node in block. Use free_space */ | ||
1148 | if (ref != jeb->last_node) { | ||
1149 | printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n", | ||
1150 | ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0); | ||
1151 | BUG(); | ||
1152 | } | ||
1153 | ref_end = jeb->offset + c->sector_size - jeb->free_size; | ||
1154 | } | ||
1155 | return ref_end - ref_offset(ref); | ||
1156 | } | ||
1157 | |||
1158 | uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
1159 | struct jffs2_raw_node_ref *ref) | ||
1160 | { | ||
1161 | uint32_t ret; | ||
1162 | |||
1163 | #if CONFIG_JFFS2_FS_DEBUG > 0 | ||
1164 | if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { | ||
1165 | printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", | ||
1166 | jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); | ||
1167 | BUG(); | ||
1168 | } | ||
1169 | #endif | ||
1170 | |||
1171 | ret = __ref_totlen(c, jeb, ref); | ||
1172 | #ifdef TEST_TOTLEN | ||
1173 | if (ret != ref->__totlen) { | ||
1174 | printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", | ||
1175 | ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, | ||
1176 | ret, ref->__totlen); | ||
1177 | if (ref->next_phys) { | ||
1178 | printk(KERN_CRIT "next_phys %p (0x%08x-0x%08x)\n", ref->next_phys, ref_offset(ref->next_phys), | ||
1179 | ref_offset(ref->next_phys)+ref->__totlen); | ||
1180 | } else | ||
1181 | printk(KERN_CRIT "No next_phys. jeb->last_node is %p\n", jeb->last_node); | ||
1182 | |||
1183 | 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); | ||
1184 | ret = ref->__totlen; | ||
1185 | if (!jeb) | ||
1186 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
1187 | #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) | ||
1188 | __jffs2_dbg_dump_node_refs_nolock(c, jeb); | ||
1189 | #endif | ||
1190 | WARN_ON(1); | ||
1191 | } | ||
1192 | #endif /* TEST_TOTLEN */ | ||
1193 | return ret; | ||
1194 | } | ||