aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-21 08:29:11 -0400
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-21 08:29:11 -0400
commitca89a517fa577e6f26621463d3aa4f3c3d530b1e (patch)
treee277f31d6629c5dcc358adfa80190fc247d43f65
parent010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7 (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.c115
-rw-r--r--fs/jffs2/nodelist.h58
-rw-r--r--fs/jffs2/nodemgmt.c6
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 */
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}
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))
225static 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
244static 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
355int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); 308int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
356void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 309void 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);
311extern 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 */
360int jffs2_thread_should_wake(struct jffs2_sb_info *c); 316int 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 }