[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>
This commit is contained in:
parent
010b06d6d0
commit
ca89a517fa
3 changed files with 121 additions and 58 deletions
|
@ -1052,8 +1052,17 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
|
|||
{
|
||||
if (!jeb->first_node)
|
||||
jeb->first_node = ref;
|
||||
if (jeb->last_node)
|
||||
if (jeb->last_node) {
|
||||
jeb->last_node->next_phys = ref;
|
||||
#ifdef TEST_TOTLEN
|
||||
if (ref_offset(jeb->last_node) + jeb->last_node->__totlen != ref_offset(ref)) {
|
||||
printk(KERN_CRIT "Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
|
||||
ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
|
||||
ref_offset(jeb->last_node), ref_offset(jeb->last_node)+jeb->last_node->__totlen);
|
||||
WARN_ON(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
jeb->last_node = ref;
|
||||
|
||||
switch(ref_flags(ref)) {
|
||||
|
@ -1076,18 +1085,110 @@ void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
|
|||
c->free_size -= len;
|
||||
jeb->free_size -= len;
|
||||
|
||||
/* Set __totlen field... for now */
|
||||
ref->__totlen = len;
|
||||
ref->next_phys = NULL;
|
||||
#ifdef TEST_TOTLEN
|
||||
/* Set (and test) __totlen field... for now */
|
||||
ref->__totlen = len;
|
||||
ref_totlen(c, jeb, ref);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* No locking. Do not use on a live file system */
|
||||
int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
|
||||
uint32_t size)
|
||||
{
|
||||
c->dirty_size += size;
|
||||
c->free_size -= size;
|
||||
jeb->dirty_size += size;
|
||||
jeb->free_size -= size;
|
||||
if (!size)
|
||||
return 0;
|
||||
if (size > c->sector_size - jeb->used_size) {
|
||||
printk(KERN_CRIT "Dirty space 0x%x larger then used_size 0x%x (wasted 0x%x)\n",
|
||||
size, jeb->used_size, jeb->wasted_size);
|
||||
BUG();
|
||||
}
|
||||
if (jeb->last_node && ref_obsolete(jeb->last_node)) {
|
||||
#ifdef TEST_TOTLEN
|
||||
jeb->last_node->__totlen += size;
|
||||
#endif
|
||||
c->dirty_size += size;
|
||||
c->free_size -= size;
|
||||
jeb->dirty_size += size;
|
||||
jeb->free_size -= size;
|
||||
} else {
|
||||
struct jffs2_raw_node_ref *ref;
|
||||
ref = jffs2_alloc_raw_node_ref();
|
||||
if (!ref)
|
||||
return -ENOMEM;
|
||||
|
||||
ref->flash_offset = jeb->offset + c->sector_size - jeb->free_size;
|
||||
ref->flash_offset |= REF_OBSOLETE;
|
||||
ref->next_in_ino = 0;
|
||||
#ifdef TEST_TOTLEN
|
||||
ref->__totlen = size;
|
||||
#endif
|
||||
|
||||
jffs2_link_node_ref(c, jeb, ref, size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate totlen from surrounding nodes or eraseblock */
|
||||
static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
|
||||
struct jffs2_eraseblock *jeb,
|
||||
struct jffs2_raw_node_ref *ref)
|
||||
{
|
||||
uint32_t ref_end;
|
||||
|
||||
if (ref->next_phys)
|
||||
ref_end = ref_offset(ref->next_phys);
|
||||
else {
|
||||
if (!jeb)
|
||||
jeb = &c->blocks[ref->flash_offset / c->sector_size];
|
||||
|
||||
/* Last node in block. Use free_space */
|
||||
if (ref != jeb->last_node) {
|
||||
printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
|
||||
ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
|
||||
BUG();
|
||||
}
|
||||
ref_end = jeb->offset + c->sector_size - jeb->free_size;
|
||||
}
|
||||
return ref_end - ref_offset(ref);
|
||||
}
|
||||
|
||||
uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
|
||||
struct jffs2_raw_node_ref *ref)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
#if CONFIG_JFFS2_FS_DEBUG > 0
|
||||
if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
|
||||
printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
|
||||
jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = __ref_totlen(c, jeb, ref);
|
||||
#ifdef TEST_TOTLEN
|
||||
if (ret != ref->__totlen) {
|
||||
printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
|
||||
ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
|
||||
ret, ref->__totlen);
|
||||
if (ref->next_phys) {
|
||||
printk(KERN_CRIT "next_phys %p (0x%08x-0x%08x)\n", ref->next_phys, ref_offset(ref->next_phys),
|
||||
ref_offset(ref->next_phys)+ref->__totlen);
|
||||
} else
|
||||
printk(KERN_CRIT "No next_phys. jeb->last_node is %p\n", jeb->last_node);
|
||||
|
||||
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);
|
||||
ret = ref->__totlen;
|
||||
if (!jeb)
|
||||
jeb = &c->blocks[ref->flash_offset / c->sector_size];
|
||||
#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
|
||||
__jffs2_dbg_dump_node_refs_nolock(c, jeb);
|
||||
#endif
|
||||
WARN_ON(1);
|
||||
}
|
||||
#endif /* TEST_TOTLEN */
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,10 @@ struct jffs2_raw_node_ref
|
|||
word so you know when you've got there :) */
|
||||
struct jffs2_raw_node_ref *next_phys;
|
||||
uint32_t flash_offset;
|
||||
#define TEST_TOTLEN
|
||||
#ifdef TEST_TOTLEN
|
||||
uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 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)
|
|||
return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
|
||||
}
|
||||
|
||||
/* Calculate totlen from surrounding nodes or eraseblock */
|
||||
static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
|
||||
struct jffs2_eraseblock *jeb,
|
||||
struct jffs2_raw_node_ref *ref)
|
||||
{
|
||||
uint32_t ref_end;
|
||||
|
||||
if (ref->next_phys)
|
||||
ref_end = ref_offset(ref->next_phys);
|
||||
else {
|
||||
if (!jeb)
|
||||
jeb = &c->blocks[ref->flash_offset / c->sector_size];
|
||||
|
||||
/* Last node in block. Use free_space */
|
||||
BUG_ON(ref != jeb->last_node);
|
||||
ref_end = jeb->offset + c->sector_size - jeb->free_size;
|
||||
}
|
||||
return ref_end - ref_offset(ref);
|
||||
}
|
||||
|
||||
static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
|
||||
struct jffs2_eraseblock *jeb,
|
||||
struct jffs2_raw_node_ref *ref)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
#if CONFIG_JFFS2_FS_DEBUG > 0
|
||||
if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
|
||||
printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
|
||||
jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
ret = ref->__totlen;
|
||||
#else
|
||||
/* This doesn't actually work yet */
|
||||
ret = __ref_totlen(c, jeb, ref);
|
||||
if (ret != ref->__totlen) {
|
||||
printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
|
||||
ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
|
||||
ret, ref->__totlen);
|
||||
if (!jeb)
|
||||
jeb = &c->blocks[ref->flash_offset / c->sector_size];
|
||||
jffs2_dbg_dump_node_refs_nolock(c, jeb);
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c))
|
||||
|
||||
#define ALLOC_NORMAL 0 /* Normal allocation */
|
||||
#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
|
|||
int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
|
||||
void jffs2_link_node_ref(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
|
||||
struct jffs2_raw_node_ref *ref, uint32_t len);
|
||||
extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
|
||||
struct jffs2_eraseblock *jeb,
|
||||
struct jffs2_raw_node_ref *ref);
|
||||
|
||||
/* nodemgmt.c */
|
||||
int jffs2_thread_should_wake(struct jffs2_sb_info *c);
|
||||
|
|
|
@ -386,7 +386,9 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r
|
|||
struct jffs2_eraseblock *jeb;
|
||||
|
||||
jeb = &c->blocks[new->flash_offset / c->sector_size];
|
||||
#ifdef TEST_TOTLEN
|
||||
new->__totlen = len;
|
||||
#endif
|
||||
|
||||
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));
|
||||
#if 1
|
||||
|
@ -679,7 +681,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
|
|||
|
||||
spin_lock(&c->erase_completion_lock);
|
||||
|
||||
#ifdef TEST_TOTLEN
|
||||
ref->__totlen += n->__totlen;
|
||||
#endif
|
||||
ref->next_phys = n->next_phys;
|
||||
if (jeb->last_node == n) jeb->last_node = ref;
|
||||
if (jeb->gc_node == n) {
|
||||
|
@ -702,7 +706,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
|
|||
p = p->next_phys;
|
||||
|
||||
if (ref_obsolete(p) && !ref->next_in_ino) {
|
||||
#ifdef TEST_TOTLEN
|
||||
p->__totlen += ref->__totlen;
|
||||
#endif
|
||||
if (jeb->last_node == ref) {
|
||||
jeb->last_node = p;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue