[JFFS2] Finally eliminate __totlen field from struct jffs2_raw_node_ref

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Sun May 21 14:59:14 EDT 2006


Commit:     ca89a517fa577e6f26621463d3aa4f3c3d530b1e
Parent:     010b06d6d07d9fa5ea6070aa72bb3e0de1761ab7
Author:     David Woodhouse <dwmw2 at infradead.org>
AuthorDate: Sun May 21 13:29:11 2006 +0100
Commit:     David Woodhouse <dwmw2 at infradead.org>
CommitDate: Sun May 21 13:29:11 2006 +0100

    [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 at infradead.org>

 fs/jffs2/nodelist.c |  115 ++++++++++++++++++++++++++++++++++++++++++++++++---
 fs/jffs2/nodelist.h |   58 +++-----------------------
 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 0050685..9a6ced0 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -1052,8 +1052,17 @@ void jffs2_link_node_ref(struct jffs2_sb
 {
 	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
 	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;
+}
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 94ef887..80d1fda 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -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_vmall
 	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 jff
 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);
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 4701556..9a0f312 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -386,7 +386,9 @@ int jffs2_add_physical_node_ref(struct j
 	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 jff
 
 		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 jff
 			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;
 			}



More information about the linux-mtd-cvs mailing list