mtd/fs/jffs2 nodelist.h,1.100,1.101 wbuf.c,1.46,1.47
write.c,1.72,1.73
David Woodhouse
dwmw2 at infradead.org
Fri Oct 3 14:14:19 EDT 2003
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv5504
Modified Files:
nodelist.h wbuf.c write.c
Log Message:
Make breakme nastier because it actually does scribble on the flash too
now. Also fix accounting code and block erasure etc.
Index: nodelist.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/nodelist.h,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -r1.100 -r1.101
--- nodelist.h 3 Oct 2003 15:54:49 -0000 1.100
+++ nodelist.h 3 Oct 2003 18:14:17 -0000 1.101
@@ -201,10 +201,11 @@
};
#define ACCT_SANITY_CHECK(c, jeb) do { \
- if (jeb->used_size + jeb->dirty_size + jeb->free_size + jeb->wasted_size + jeb->unchecked_size != c->sector_size) { \
- printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \
+ struct jffs2_eraseblock *___j = jeb; \
+ if ((___j) && ___j->used_size + ___j->dirty_size + ___j->free_size + ___j->wasted_size + ___j->unchecked_size != c->sector_size) { \
+ printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", ___j->offset); \
printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \
- jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, jeb->unchecked_size, c->sector_size); \
+ ___j->free_size, ___j->dirty_size, ___j->used_size, ___j->wasted_size, ___j->unchecked_size, c->sector_size); \
BUG(); \
} \
if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \
Index: wbuf.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/wbuf.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -r1.46 -r1.47
--- wbuf.c 3 Oct 2003 16:37:43 -0000 1.46
+++ wbuf.c 3 Oct 2003 18:14:17 -0000 1.47
@@ -21,6 +21,10 @@
/* For testing write failures */
//#define BREAKME
+#ifdef BREAKME
+static unsigned char *brokenbuf;
+#endif
+
/* max. erase failures before we mark a block bad */
#define MAX_ERASE_FAILURES 5
@@ -139,23 +143,48 @@
jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
+ D1(printk("About to refile bad block at %08x\n", jeb->offset));
+
+ D1(jffs2_dump_block_lists(c));
/* File the existing block on the bad_used_list.... */
if (c->nextblock == jeb)
c->nextblock = NULL;
else /* Not sure this should ever happen... need more coffee */
list_del(&jeb->list);
- list_add(&jeb->list, &c->bad_used_list);
+ if (jeb->first_node) {
+ D1(printk("Refiling block at %08x to bad_used_list\n", jeb->offset));
+ list_add(&jeb->list, &c->bad_used_list);
+ } else {
+ BUG();
+ /* It has to have had some nodes or we couldn't be here */
+ D1(printk("Refiling block at %08x to erase_pending_list\n", jeb->offset));
+ list_add(&jeb->list, &c->erase_pending_list);
+ c->nr_erasing_blocks++;
+ jffs2_erase_pending_trigger(c);
+ }
+ D1(jffs2_dump_block_lists(c));
/* Adjust its size counts accordingly */
- jeb->wasted_size += jeb->free_size;
- c->wasted_size += jeb->free_size;
+ c->dirty_size += jeb->free_size;
c->free_size -= jeb->free_size;
+ jeb->dirty_size += jeb->free_size;
jeb->free_size = 0;
-
+
+ c->dirty_size += jeb->wasted_size;
+ c->wasted_size -= jeb->wasted_size;
+ jeb->dirty_size += jeb->wasted_size;
+ jeb->wasted_size = 0;
+
/* Find the first node to be recovered */
first_raw = &jeb->first_node;
- while (*first_raw && ref_offset(*first_raw) < c->wbuf_ofs && !ref_obsolete(*first_raw))
+ while (*first_raw && !ref_obsolete(*first_raw) &&
+ (ref_offset(*first_raw) + (*first_raw)->totlen) < c->wbuf_ofs) {
+ D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
+ ref_offset(*first_raw), ref_flags(*first_raw),
+ (ref_offset(*first_raw) + (*first_raw)->totlen),
+ c->wbuf_ofs));
first_raw = &(*first_raw)->next_phys;
+ }
if (!*first_raw) {
/* All nodes were obsolete. Nothing to recover. */
@@ -233,20 +262,26 @@
the wbuf. Since if we're writing from the wbuf there
won't be more than a wbuf full of data, now will
there? :) */
+
+ uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize);
+
D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n",
- (end-start) - ((end-start)%c->wbuf_pagesize), ofs));
+ towrite, ofs));
- ret = c->mtd->write_ecc(c->mtd, ofs,
- (end-start) - ((end-start)%c->wbuf_pagesize),
- &retlen, buf, NULL, c->oobinfo);
#ifdef BREAKME
static int breakme;
- if (breakme++ == 40) {
+ if (breakme++ == 20) {
+ printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs);
breakme = 0;
+ c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
+ brokenbuf, NULL, c->oobinfo);
ret = -EIO;
- }
+ } else
#endif
- if (!ret || retlen != (end-start)%c->wbuf_pagesize) {
+ ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
+ buf, NULL, c->oobinfo);
+
+ if (ret || retlen != towrite) {
/* Argh. We tried. Really we did. */
printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
kfree(buf);
@@ -318,8 +353,14 @@
/* Fix up the original jeb now it's on the bad_list */
*first_raw = NULL;
- if (first_raw == &jeb->first_node)
+ if (first_raw == &jeb->first_node) {
jeb->last_node = NULL;
+ D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset));
+ list_del(&jeb->list);
+ list_add(&jeb->list, &c->erase_pending_list);
+ c->nr_erasing_blocks++;
+ jffs2_erase_pending_trigger(c);
+ }
else
jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys);
@@ -378,15 +419,18 @@
/* else jffs2_flash_writev has actually filled in the rest of the
buffer for us, and will deal with the node refs etc. later. */
- ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
-
#ifdef BREAKME
static int breakme;
- if (breakme++ == 40) {
+ if (breakme++ == 20) {
+ printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs);
breakme = 0;
+ c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize,
+ &retlen, brokenbuf, NULL, c->oobinfo);
ret = -EIO;
- }
+ } else
#endif
+ ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
+
if (ret || retlen != c->wbuf_pagesize) {
if (ret)
@@ -1079,6 +1123,15 @@
if (!c->wbuf)
return -ENOMEM;
+#ifdef BREAKME
+ if (!brokenbuf)
+ brokenbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
+ if (!brokenbuf) {
+ kfree(c->wbuf);
+ return -ENOMEM;
+ }
+ memset(brokenbuf, 0xdb, c->wbuf_pagesize);
+#endif
return 0;
}
Index: write.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/write.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- write.c 3 Oct 2003 16:24:53 -0000 1.72
+++ write.c 3 Oct 2003 18:14:17 -0000 1.73
@@ -163,10 +163,14 @@
if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
/* Try to reallocate space and retry */
uint32_t dummy;
+ struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
retried = 1;
D1(printk(KERN_DEBUG "Retrying failed write.\n"));
+
+ ACCT_SANITY_CHECK(c,jeb);
+ D1(ACCT_PARANOIA_CHECK(jeb));
if (alloc_mode == ALLOC_GC) {
ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy);
@@ -181,6 +185,10 @@
if (!ret) {
D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
+
+ ACCT_SANITY_CHECK(c,jeb);
+ D1(ACCT_PARANOIA_CHECK(jeb));
+
goto retry;
}
D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
@@ -213,6 +221,10 @@
je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
+ if (retried) {
+ ACCT_SANITY_CHECK(c,NULL);
+ }
+
return fn;
}
@@ -284,11 +296,15 @@
if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
/* Try to reallocate space and retry */
uint32_t dummy;
+ struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
retried = 1;
D1(printk(KERN_DEBUG "Retrying failed write.\n"));
+ ACCT_SANITY_CHECK(c,jeb);
+ D1(ACCT_PARANOIA_CHECK(jeb));
+
if (alloc_mode == ALLOC_GC) {
ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy);
} else {
@@ -302,6 +318,8 @@
if (!ret) {
D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
+ ACCT_SANITY_CHECK(c,jeb);
+ D1(ACCT_PARANOIA_CHECK(jeb));
goto retry;
}
D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
@@ -317,6 +335,10 @@
raw->next_in_ino = f->inocache->nodes;
f->inocache->nodes = raw;
+
+ if (retried) {
+ ACCT_SANITY_CHECK(c,NULL);
+ }
return fd;
}
More information about the linux-mtd-cvs
mailing list