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