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