diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-05-21 08:29:11 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-05-21 08:29:11 -0400 |
commit | ca89a517fa577e6f26621463d3aa4f3c3d530b1e (patch) | |
tree | e277f31d6629c5dcc358adfa80190fc247d43f65 | |
parent | 010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7 (diff) |
[JFFS2] Finally eliminate __totlen field from struct jffs2_raw_node_ref
Well, almost. We'll actually keep a 'TEST_TOTLEN' macro set for now, and keep
doing some paranoia checks to make sure it's all working correctly. But if
TEST_TOTLEN is unset, the size of struct jffs2_raw_node_ref drops from 16
bytes to 12 on 32-bit machines. That's a saving of about half a megabyte of
memory on the OLPC prototype board, with 125K or so nodes in its 512MiB of
flash.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r-- | fs/jffs2/nodelist.c | 115 | ||||
-rw-r--r-- | fs/jffs2/nodelist.h | 58 | ||||
-rw-r--r-- | fs/jffs2/nodemgmt.c | 6 |
3 files changed, 121 insertions, 58 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 | } | ||
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 94ef88787347..80d1fda2212b 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -82,7 +82,10 @@ struct jffs2_raw_node_ref | |||
82 | word so you know when you've got there :) */ | 82 | word so you know when you've got there :) */ |
83 | struct jffs2_raw_node_ref *next_phys; | 83 | struct jffs2_raw_node_ref *next_phys; |
84 | uint32_t flash_offset; | 84 | uint32_t flash_offset; |
85 | #define TEST_TOTLEN | ||
86 | #ifdef TEST_TOTLEN | ||
85 | uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ | 87 | uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ |
88 | #endif | ||
86 | }; | 89 | }; |
87 | 90 | ||
88 | /* flash_offset & 3 always has to be zero, because nodes are | 91 | /* flash_offset & 3 always has to be zero, because nodes are |
@@ -221,57 +224,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c) | |||
221 | return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); | 224 | return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); |
222 | } | 225 | } |
223 | 226 | ||
224 | /* Calculate totlen from surrounding nodes or eraseblock */ | 227 | #define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c)) |
225 | static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, | ||
226 | struct jffs2_eraseblock *jeb, | ||
227 | struct jffs2_raw_node_ref *ref) | ||
228 | { | ||
229 | uint32_t ref_end; | ||
230 | |||
231 | if (ref->next_phys) | ||
232 | ref_end = ref_offset(ref->next_phys); | ||
233 | else { | ||
234 | if (!jeb) | ||
235 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
236 | |||
237 | /* Last node in block. Use free_space */ | ||
238 | BUG_ON(ref != jeb->last_node); | ||
239 | ref_end = jeb->offset + c->sector_size - jeb->free_size; | ||
240 | } | ||
241 | return ref_end - ref_offset(ref); | ||
242 | } | ||
243 | |||
244 | static inline uint32_t ref_totlen(struct jffs2_sb_info *c, | ||
245 | struct jffs2_eraseblock *jeb, | ||
246 | struct jffs2_raw_node_ref *ref) | ||
247 | { | ||
248 | uint32_t ret; | ||
249 | |||
250 | #if CONFIG_JFFS2_FS_DEBUG > 0 | ||
251 | if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { | ||
252 | printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", | ||
253 | jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); | ||
254 | BUG(); | ||
255 | } | ||
256 | #endif | ||
257 | |||
258 | #if 1 | ||
259 | ret = ref->__totlen; | ||
260 | #else | ||
261 | /* This doesn't actually work yet */ | ||
262 | ret = __ref_totlen(c, jeb, ref); | ||
263 | if (ret != ref->__totlen) { | ||
264 | printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", | ||
265 | ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, | ||
266 | ret, ref->__totlen); | ||
267 | if (!jeb) | ||
268 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
269 | jffs2_dbg_dump_node_refs_nolock(c, jeb); | ||
270 | BUG(); | ||
271 | } | ||
272 | #endif | ||
273 | return ret; | ||
274 | } | ||
275 | 228 | ||
276 | #define ALLOC_NORMAL 0 /* Normal allocation */ | 229 | #define ALLOC_NORMAL 0 /* Normal allocation */ |
277 | #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ | 230 | #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ |
@@ -355,6 +308,9 @@ void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uin | |||
355 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); | 308 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); |
356 | void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 309 | void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
357 | struct jffs2_raw_node_ref *ref, uint32_t len); | 310 | struct jffs2_raw_node_ref *ref, uint32_t len); |
311 | extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, | ||
312 | struct jffs2_eraseblock *jeb, | ||
313 | struct jffs2_raw_node_ref *ref); | ||
358 | 314 | ||
359 | /* nodemgmt.c */ | 315 | /* nodemgmt.c */ |
360 | int jffs2_thread_should_wake(struct jffs2_sb_info *c); | 316 | int jffs2_thread_should_wake(struct jffs2_sb_info *c); |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 4701556be49d..9a0f312cfcda 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -386,7 +386,9 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
386 | struct jffs2_eraseblock *jeb; | 386 | struct jffs2_eraseblock *jeb; |
387 | 387 | ||
388 | jeb = &c->blocks[new->flash_offset / c->sector_size]; | 388 | jeb = &c->blocks[new->flash_offset / c->sector_size]; |
389 | #ifdef TEST_TOTLEN | ||
389 | new->__totlen = len; | 390 | new->__totlen = len; |
391 | #endif | ||
390 | 392 | ||
391 | D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); | 393 | D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); |
392 | #if 1 | 394 | #if 1 |
@@ -679,7 +681,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
679 | 681 | ||
680 | spin_lock(&c->erase_completion_lock); | 682 | spin_lock(&c->erase_completion_lock); |
681 | 683 | ||
684 | #ifdef TEST_TOTLEN | ||
682 | ref->__totlen += n->__totlen; | 685 | ref->__totlen += n->__totlen; |
686 | #endif | ||
683 | ref->next_phys = n->next_phys; | 687 | ref->next_phys = n->next_phys; |
684 | if (jeb->last_node == n) jeb->last_node = ref; | 688 | if (jeb->last_node == n) jeb->last_node = ref; |
685 | if (jeb->gc_node == n) { | 689 | if (jeb->gc_node == n) { |
@@ -702,7 +706,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
702 | p = p->next_phys; | 706 | p = p->next_phys; |
703 | 707 | ||
704 | if (ref_obsolete(p) && !ref->next_in_ino) { | 708 | if (ref_obsolete(p) && !ref->next_in_ino) { |
709 | #ifdef TEST_TOTLEN | ||
705 | p->__totlen += ref->__totlen; | 710 | p->__totlen += ref->__totlen; |
711 | #endif | ||
706 | if (jeb->last_node == ref) { | 712 | if (jeb->last_node == ref) { |
707 | jeb->last_node = p; | 713 | jeb->last_node = p; |
708 | } | 714 | } |