Commit 6507d385 authored by David Woodhouse's avatar David Woodhouse Committed by David Woodhouse

JFFS2 updates

 - 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: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent ce9ef9d9
......@@ -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);
......
......@@ -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 $
*
*/
......
......@@ -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;
}
......
......@@ -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(); \
} \
......
......@@ -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
......
......@@ -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;
......
......@@ -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 $
*
*/
......
......@@ -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;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment