JFFS2 eats memory

Øyvind Harboe oyvind.harboe at zylin.com
Tue Jul 20 09:37:20 EDT 2004


> gc_node is the next node to be garbage-collected. We don't need to
> garbage-collect nodes which are already obsolete. So if you're freeing
> the object which is currently pointed to by jeb->gc_node, you can just
> make gc_node point to the next_phys node which you're _not_ freeing.

I modified the code to have gc continue on the previous node(the next
node does not always exist).



-- 
Øyvind Harboe
http://www.zylin.com

-------------- next part --------------
? gcmemfix.txt
? memfix.txt
? memfixgc.txt
? memleakfix.txt
? mutex.txt
? oyvind at 84.234.138.230
Index: build.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/build.c,v
retrieving revision 1.5
diff -w -u -r1.5 build.c
--- build.c	20 Nov 2003 16:52:36 -0000	1.5
+++ build.c	20 Jul 2004 13:35:11 -0000
@@ -259,6 +259,14 @@
 
 	c->resv_blocks_write = c->resv_blocks_deletion + (size / c->sector_size);
 
+	// If the flash disk is smaller than resv_blocks_write, then we 
+	// allow writing to the disk anyway. The flash disk is then most likely
+	// being used as write once - read many medimum, e.g. configuration of 
+	// static paramters.
+	if (c->resv_blocks_write * c->sector_size > c->flash_size) {
+	  c->resv_blocks_write = 0; 
+	}
+
 	/* When do we let the GC thread run in the background */
 
 	c->resv_blocks_gctrigger = c->resv_blocks_write + 1;
Index: dir-ecos.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/dir-ecos.c,v
retrieving revision 1.5
diff -w -u -r1.5 dir-ecos.c
--- dir-ecos.c	11 Dec 2003 23:33:54 -0000	1.5
+++ dir-ecos.c	20 Jul 2004 13:35:11 -0000
@@ -48,9 +48,11 @@
 	up(&dir_f->sem);
 	if (ino) {
 		inode = jffs2_iget(dir_i->i_sb, ino);
-		if (!inode) {
+		if (IS_ERR(inode)) {
 			printk("jffs2_iget() failed for ino #%u\n", ino);
-			return (ERR_PTR(-EIO));
+			// NOTE! inode is *not* a pointer here, but an
+			// error code we propagate.
+			return inode;
 		}
 	}
 
Index: erase.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/erase.c,v
retrieving revision 1.6
diff -w -u -r1.6 erase.c
--- erase.c	11 Dec 2003 23:33:54 -0000	1.6
+++ erase.c	20 Jul 2004 13:35:11 -0000
@@ -365,11 +365,12 @@
 		jeb->dirty_size = 0;
 		jeb->wasted_size = 0;
 	} else {
-		struct jffs2_unknown_node marker = {
-			.magic =	cpu_to_je16(JFFS2_MAGIC_BITMASK),
-			.nodetype =	cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
-			.totlen =	cpu_to_je32(c->cleanmarker_size)
-		};
+		
+		struct jffs2_unknown_node marker;
+		memset(&marker, 0, sizeof(marker));
+		marker.magic =	cpu_to_je16(JFFS2_MAGIC_BITMASK);
+		marker.nodetype =	cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
+		marker.totlen =	cpu_to_je32(c->cleanmarker_size);
 
 		marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
 
Index: fs-ecos.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/fs-ecos.c,v
retrieving revision 1.27
diff -w -u -r1.27 fs-ecos.c
--- fs-ecos.c	21 Apr 2004 18:51:21 -0000	1.27
+++ fs-ecos.c	20 Jul 2004 13:35:12 -0000
@@ -302,7 +302,7 @@
 	d = jffs2_lookup(dir, name, namelen);
 	D2(printf("find_entry got dir = %x\n", d));
 
-	if (d == NULL)
+	if ((d==NULL)||IS_ERR(d))
 		return ENOENT;
 
 	// If it's a new directory inode, increase refcount on its parent
Index: gc.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/gc.c,v
retrieving revision 1.7
diff -w -u -r1.7 gc.c
--- gc.c	1 Apr 2004 03:17:57 -0000	1.7
+++ gc.c	20 Jul 2004 13:35:13 -0000
@@ -358,10 +358,10 @@
 	spin_unlock(&c->inocache_lock);
 
 	f = jffs2_gc_fetch_inode(c, inum, nlink);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
-	if (!f)
-		return 0;
+	if (!f||IS_ERR(f)) {
+	  up(&c->alloc_sem);
+		return f;
+	}
 
 	ret = jffs2_garbage_collect_live(c, jeb, raw, f);
 
Index: nodemgmt.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/fs/jffs2/current/src/nodemgmt.c,v
retrieving revision 1.6
diff -w -u -r1.6 nodemgmt.c
--- nodemgmt.c	11 Dec 2003 23:33:54 -0000	1.6
+++ nodemgmt.c	20 Jul 2004 13:35:13 -0000
@@ -549,6 +549,59 @@
 		printk(KERN_WARNING "Short write in obliterating obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen);
 		return;
 	}
+
+	/* Nodes which have been marked obsolete no longer need to be
+	   associated with any inode. Remove them from the per-inode list */
+	if (ref->next_in_ino) {
+		struct jffs2_inode_cache *ic;
+		struct jffs2_raw_node_ref **p;
+
+		ic = jffs2_raw_ref_to_ic(ref);
+		for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino))
+			;
+
+		*p = ref->next_in_ino;
+		ref->next_in_ino = NULL;
+	}
+
+
+	/* Merge with the next node in the physical list, if there is one
+	   and if it's also obsolete. */
+	if (ref->next_phys && ref_obsolete(ref->next_phys) ) {
+		struct jffs2_raw_node_ref *n = ref->next_phys;
+		
+		ref->__totlen += n->__totlen;
+		/* we don't need to check jeb->last_node */
+		ref->next_phys = n->next_phys;
+		if (jeb->gc_node == n) {
+			/* gc will be happy continuing gc on this node */
+			jeb->gc_node=ref;
+		}
+		BUG_ON(n->next_in_ino);
+		jffs2_free_raw_node_ref(n);
+	}
+	
+	/* Also merge with the previous node in the list, if there is one
+	   and that one is obsolete */
+	if (ref != jeb->first_node ) {
+		struct jffs2_raw_node_ref *p = jeb->first_node;
+		
+		while (p->next_phys != ref)
+			p = p->next_phys;
+		
+		if (ref_obsolete(p) ) {
+			p->__totlen += ref->__totlen;
+			if (jeb->last_node == ref) {
+				jeb->last_node = p;
+			}
+			if (jeb->gc_node == ref) {
+				/* gc will be happy continuing gc on this node */
+				jeb->gc_node=p;
+			}
+			p->next_phys = ref->next_phys;
+			jffs2_free_raw_node_ref(ref);
+		}
+	}
 }
 
 #if CONFIG_JFFS2_FS_DEBUG > 0


More information about the linux-mtd mailing list