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.c115
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 */
1084int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 1097int 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 */
1135static 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
1158uint32_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}