]> git.neil.brown.name Git - history.git/commitdiff
JFFS2 updates
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>
Thu, 21 Oct 2004 02:05:56 +0000 (03:05 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Thu, 21 Oct 2004 02:05:56 +0000 (03:05 +0100)
 - Reduce memory use by merging adjacent obsolete raw_node_refs
 - Error handling fixes
 - Respect kmalloc size limit in scan
 - NAND ECC updates

Signed-Off-By: David Woodhouse <dwmw2@infradead.org>
fs/jffs2/dir.c
fs/jffs2/erase.c
fs/jffs2/gc.c
fs/jffs2/nodelist.h
fs/jffs2/nodemgmt.c
fs/jffs2/scan.c
fs/jffs2/super.c
fs/jffs2/wbuf.c

index 561e37f3d64407aef94d6b4e34ad51e793ff3ccd..0ec0be3f0bbae8de6df721027f5cb1e8ae84c5b7 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: dir.c,v 1.82 2003/10/11 11:47:23 dwmw2 Exp $
+ * $Id: dir.c,v 1.83 2004/10/19 07:48:44 havasi Exp $
  *
  */
 
@@ -217,7 +217,6 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
                              dentry->d_name.name, dentry->d_name.len);
 
        if (ret) {
-               jffs2_clear_inode(inode);
                make_bad_inode(inode);
                iput(inode);
                jffs2_free_raw_inode(ri);
index f6efdbabbf3e20b674cf8ac086a9574356265fd1..724e7ee0e82eeb2fa0fd0914d4b2389b2bc67323 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: erase.c,v 1.60 2004/06/30 17:26:15 dbrown Exp $
+ * $Id: erase.c,v 1.61 2004/10/20 23:59:49 dwmw2 Exp $
  *
  */
 
index dc25d812a3c0f450827d45a2d566395b2d9e1caf..93f6b27239c7c26558919bb75bc37890e824e867 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: gc.c,v 1.136 2004/05/27 19:06:09 gleixner Exp $
+ * $Id: gc.c,v 1.137 2004/07/20 13:44:55 dwmw2 Exp $
  *
  */
 
@@ -359,10 +359,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
        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 (IS_ERR(f)) {
+               ret = PTR_ERR(f);
+               goto release_sem;
+       }
+       if (!f) {
+               ret = 0;
+               goto release_sem;
+       }
 
        ret = jffs2_garbage_collect_live(c, jeb, raw, f);
 
@@ -824,7 +828,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct
                                continue;
                        }
                        if (retlen != rawlen) {
-                               printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %u) reading header from obsolete node at %08x\n",
+                               printk(KERN_WARNING "jffs2_g_c_deletion_dirent(): Short read (%zd not %zd) reading header from obsolete node at %08x\n",
                                       retlen, rawlen, ref_offset(raw));
                                continue;
                        }
index cea0c139018495d4d92c83d9fea9678c703a9ddb..7b5f8822b7e479cb6b799dc0b202f0e0273d8aa1 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodelist.h,v 1.119 2004/05/26 12:28:12 gleixner Exp $
+ * $Id: nodelist.h,v 1.120 2004/10/07 15:11:54 havasi Exp $
  *
  */
 
@@ -281,9 +281,14 @@ static inline void paranoia_failed_dump(struct jffs2_eraseblock *jeb)
                        else if (!ref_obsolete(ref2)) \
                                my_used_size += ref_totlen(c, jeb, ref2); \
                        if (unlikely((!ref2->next_phys) != (ref2 == jeb->last_node))) { \
-                               printk("ref for node at %p (phys %08x) has next_phys->%p (%08x), last_node->%p (phys %08x)\n", \
-                                      ref2, ref_offset(ref2), ref2->next_phys, ref_offset(ref2->next_phys), \
-                                      jeb->last_node, ref_offset(jeb->last_node)); \
+                                if (!ref2->next_phys) \
+                                      printk("ref for node at %p (phys %08x) has next_phys->%p (----), last_node->%p (phys %08x)\n", \
+                                            ref2, ref_offset(ref2), ref2->next_phys, \
+                                            jeb->last_node, ref_offset(jeb->last_node)); \
+                                else \
+                                       printk("ref for node at %p (phys %08x) has next_phys->%p (%08x), last_node->%p (phys %08x)\n", \
+                                            ref2, ref_offset(ref2), ref2->next_phys, ref_offset(ref2->next_phys), \
+                                            jeb->last_node, ref_offset(jeb->last_node)); \
                                paranoia_failed_dump(jeb); \
                                BUG(); \
                        } \
index 5043d1a6f3d1626d5727322862d8555d8d6af145..322395b81ffe16e91deaa4520d60b0ceaa7acddb 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: nodemgmt.c,v 1.107 2003/11/26 15:30:58 dwmw2 Exp $
+ * $Id: nodemgmt.c,v 1.109 2004/10/07 15:08:47 havasi Exp $
  *
  */
 
@@ -549,6 +549,59 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
                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;
+               ref->next_phys = n->next_phys;
+                if (jeb->last_node == n) jeb->last_node = ref;
+               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
index 67a1d1bce71d8b0d63b8df5fa1fe166c0b9df611..1ddd6bf1a3c9c8f6aa226ee02380bb7e22500d1d 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: scan.c,v 1.110 2004/06/17 17:15:31 gleixner Exp $
+ * $Id: scan.c,v 1.112 2004/09/12 09:56:13 gleixner Exp $
  *
  */
 #include <linux/kernel.h>
@@ -104,6 +104,10 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
                else
                        buf_size = PAGE_SIZE;
 
+               /* Respect kmalloc limitations */
+               if (buf_size > 128*1024)
+                       buf_size = 128*1024;
+
                D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
                flashbuf = kmalloc(buf_size, GFP_KERNEL);
                if (!flashbuf)
@@ -237,7 +241,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        }
 #endif
        if (c->nr_erasing_blocks) {
-               if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
+               if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { 
                        printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
                        printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks);
                        ret = -EIO;
index 257a06ea0b3a8e8b1fbb86fbb040a40fe0ffa283..30cc15eed7dd1e3d5bf836ff048722073b0bdd4b 100644 (file)
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: super.c,v 1.99 2004/08/24 07:59:57 dwmw2 Exp $
+ * $Id: super.c,v 1.100 2004/10/21 00:03:50 dwmw2 Exp $
  *
  */
 
index 2470eef95ae5a8b3e9932b5db209b35198e3c5d3..254f441647afaaa552aa84209856437be12e5591 100644 (file)
@@ -9,7 +9,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: wbuf.c,v 1.70 2004/07/13 08:58:25 dwmw2 Exp $
+ * $Id: wbuf.c,v 1.72 2004/09/11 19:22:43 gleixner Exp $
  *
  */
 
@@ -225,7 +225,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
 
                /* Do the read... */
                ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo);
-               if (ret == -EIO && retlen == c->wbuf_ofs - start) {
+               if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) {
                        /* ECC recovered */
                        ret = 0;
                }
@@ -791,7 +791,7 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
        if (!jffs2_can_mark_obsolete(c)) {
                ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);
 
-               if ( (ret == -EIO) && (*retlen == len) ) {
+               if ( (ret == -EBADMSG) && (*retlen == len) ) {
                        printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
                               len, ofs);
                        /* 
@@ -1047,7 +1047,7 @@ int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
        if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
                D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
                /* Get the position of the free bytes */
-               if (!oinfo->oobfree[0][0]) {
+               if (!oinfo->oobfree[0][1]) {
                        printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
                        return -ENOSPC;
                }